Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
d85be261b2
commit
53716bea26
|
@ -83,7 +83,7 @@ export default {
|
|||
<gl-badge variant="warning">{{ __('pending deletion') }}</gl-badge>
|
||||
</div>
|
||||
<div v-if="isProject" class="last-updated">
|
||||
<time-ago-tooltip :time="item.updatedAt" tooltip-placement="bottom" />
|
||||
<time-ago-tooltip :time="item.lastActivityAt" tooltip-placement="bottom" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -98,6 +98,9 @@ export default class GroupsStore {
|
|||
updatedAt: rawGroupItem.updated_at,
|
||||
pendingRemoval: rawGroupItem.marked_for_deletion,
|
||||
microdata: this.showSchemaMarkup ? getGroupItemMicrodata(rawGroupItem) : {},
|
||||
lastActivityAt: rawGroupItem.last_activity_at
|
||||
? rawGroupItem.last_activity_at
|
||||
: rawGroupItem.updated_at,
|
||||
};
|
||||
|
||||
if (!isEmpty(rawGroupItem.compliance_management_framework)) {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
<script>
|
||||
import { GlButton, GlModalDirective, GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui';
|
||||
import axios from 'axios';
|
||||
import * as Sentry from '@sentry/browser';
|
||||
import { mapState, mapActions, mapGetters } from 'vuex';
|
||||
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
|
||||
|
@ -10,6 +11,7 @@ import {
|
|||
I18N_SUCCESSFUL_CONNECTION_MESSAGE,
|
||||
integrationLevels,
|
||||
} from '~/integrations/constants';
|
||||
import { refreshCurrentPage } from '~/lib/utils/url_utility';
|
||||
import eventHub from '../event_hub';
|
||||
import { testIntegrationSettings } from '../api';
|
||||
import ActiveCheckbox from './active_checkbox.vue';
|
||||
|
@ -55,11 +57,12 @@ export default {
|
|||
integrationActive: false,
|
||||
isTesting: false,
|
||||
isSaving: false,
|
||||
isResetting: false,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['currentKey', 'propsSource']),
|
||||
...mapState(['defaultState', 'customState', 'override', 'isResetting']),
|
||||
...mapState(['defaultState', 'customState', 'override']),
|
||||
isEditable() {
|
||||
return this.propsSource.editable;
|
||||
},
|
||||
|
@ -126,7 +129,20 @@ export default {
|
|||
});
|
||||
},
|
||||
onResetClick() {
|
||||
this.fetchResetIntegration();
|
||||
this.isResetting = true;
|
||||
|
||||
return axios
|
||||
.post(this.propsSource.resetPath)
|
||||
.then(() => {
|
||||
refreshCurrentPage();
|
||||
})
|
||||
.catch((error) => {
|
||||
this.$toast.show(I18N_DEFAULT_ERROR_MESSAGE);
|
||||
Sentry.captureException(error);
|
||||
})
|
||||
.finally(() => {
|
||||
this.isResetting = false;
|
||||
});
|
||||
},
|
||||
onRequestJiraIssueTypes() {
|
||||
this.requestJiraIssueTypes(this.getFormData());
|
||||
|
@ -208,6 +224,7 @@ export default {
|
|||
variant="confirm"
|
||||
:loading="isSaving"
|
||||
:disabled="disableButtons"
|
||||
data-testid="save-button-instance-group"
|
||||
data-qa-selector="save_changes_button"
|
||||
>
|
||||
{{ __('Save changes') }}
|
||||
|
|
|
@ -11,7 +11,7 @@ export default {
|
|||
primaryProps() {
|
||||
return {
|
||||
text: __('Reset'),
|
||||
attributes: [{ variant: 'warning' }, { category: 'primary' }],
|
||||
attributes: [{ variant: 'danger' }, { category: 'primary' }],
|
||||
};
|
||||
},
|
||||
cancelProps() {
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
import axios from 'axios';
|
||||
import { refreshCurrentPage } from '~/lib/utils/url_utility';
|
||||
import {
|
||||
VALIDATE_INTEGRATION_FORM_EVENT,
|
||||
I18N_FETCH_TEST_SETTINGS_DEFAULT_ERROR_MESSAGE,
|
||||
|
@ -10,27 +8,6 @@ import eventHub from '../event_hub';
|
|||
import * as types from './mutation_types';
|
||||
|
||||
export const setOverride = ({ commit }, override) => commit(types.SET_OVERRIDE, override);
|
||||
export const setIsResetting = ({ commit }, isResetting) =>
|
||||
commit(types.SET_IS_RESETTING, isResetting);
|
||||
|
||||
export const requestResetIntegration = ({ commit }) => {
|
||||
commit(types.REQUEST_RESET_INTEGRATION);
|
||||
};
|
||||
export const receiveResetIntegrationSuccess = () => {
|
||||
refreshCurrentPage();
|
||||
};
|
||||
export const receiveResetIntegrationError = ({ commit }) => {
|
||||
commit(types.RECEIVE_RESET_INTEGRATION_ERROR);
|
||||
};
|
||||
|
||||
export const fetchResetIntegration = ({ dispatch, getters }) => {
|
||||
dispatch('requestResetIntegration');
|
||||
|
||||
return axios
|
||||
.post(getters.propsSource.resetPath, { params: { format: 'json' } })
|
||||
.then(() => dispatch('receiveResetIntegrationSuccess'))
|
||||
.catch(() => dispatch('receiveResetIntegrationError'));
|
||||
};
|
||||
|
||||
export const requestJiraIssueTypes = ({ commit, dispatch, getters }, formData) => {
|
||||
commit(types.SET_JIRA_ISSUE_TYPES_ERROR_MESSAGE, '');
|
||||
|
|
|
@ -4,15 +4,6 @@ export default {
|
|||
[types.SET_OVERRIDE](state, override) {
|
||||
state.override = override;
|
||||
},
|
||||
[types.SET_IS_RESETTING](state, isResetting) {
|
||||
state.isResetting = isResetting;
|
||||
},
|
||||
[types.REQUEST_RESET_INTEGRATION](state) {
|
||||
state.isResetting = true;
|
||||
},
|
||||
[types.RECEIVE_RESET_INTEGRATION_ERROR](state) {
|
||||
state.isResetting = false;
|
||||
},
|
||||
[types.SET_JIRA_ISSUE_TYPES](state, jiraIssueTypes) {
|
||||
state.jiraIssueTypes = jiraIssueTypes;
|
||||
},
|
||||
|
|
|
@ -5,8 +5,6 @@ export default ({ defaultState = null, customState = {} } = {}) => {
|
|||
override,
|
||||
defaultState,
|
||||
customState,
|
||||
isSaving: false,
|
||||
isResetting: false,
|
||||
isLoadingJiraIssueTypes: false,
|
||||
loadingJiraIssueTypesErrorMessage: '',
|
||||
jiraIssueTypes: [],
|
||||
|
|
|
@ -3,7 +3,7 @@ import Vue from 'vue';
|
|||
import { parseBoolean } from '~/lib/utils/common_utils';
|
||||
import PerformancePlugin from '~/performance/vue_performance_plugin';
|
||||
import Translate from '~/vue_shared/translate';
|
||||
import RegistryBreadcrumb from './components/registry_breadcrumb.vue';
|
||||
import RegistryBreadcrumb from '~/packages_and_registries/shared/components/registry_breadcrumb.vue';
|
||||
import { apolloProvider } from './graphql/index';
|
||||
import RegistryExplorer from './pages/index.vue';
|
||||
import createRouter from './router';
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
import { GlSafeHtmlDirective } from '@gitlab/ui';
|
||||
import LineNumbers from '~/vue_shared/components/line_numbers.vue';
|
||||
import { sanitize } from '~/lib/dompurify';
|
||||
import '~/sourcegraph/load';
|
||||
|
||||
const LINE_SELECT_CLASS_NAME = 'hll';
|
||||
|
||||
|
|
|
@ -293,10 +293,8 @@
|
|||
}
|
||||
}
|
||||
|
||||
.modal-doorkeepr-auth {
|
||||
.modal-body {
|
||||
padding: $gl-padding;
|
||||
}
|
||||
.doorkeeper-authorize {
|
||||
max-width: px-to-rem(500px);
|
||||
}
|
||||
|
||||
.created-deploy-token-container {
|
||||
|
|
|
@ -33,6 +33,8 @@ class GroupChildEntity < Grape::Entity
|
|||
end
|
||||
|
||||
# Project only attributes
|
||||
expose :last_activity_at, if: lambda { |instance| project? }
|
||||
|
||||
expose :star_count, :archived,
|
||||
if: lambda { |_instance, _options| project? }
|
||||
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
%main{ :role => "main" }
|
||||
.modal-dialog.modal-doorkeepr-auth
|
||||
.modal-content.gl-shadow-none
|
||||
.modal-header
|
||||
%h3.page-title
|
||||
.doorkeeper-authorize.gl-mx-auto.gl-mt-6
|
||||
.gl-border-gray-200.gl-border-1.gl-border-solid.gl-rounded-base
|
||||
.gl-p-5.gl-border-b-gray-200.gl-border-b-1.gl-border-b-solid
|
||||
%h4.gl-m-0
|
||||
- link_to_client = link_to(@pre_auth.client.name, @pre_auth.redirect_uri, target: '_blank', rel: 'noopener noreferrer')
|
||||
= _("Authorize %{link_to_client} to use your account?").html_safe % { link_to_client: link_to_client }
|
||||
|
||||
.modal-body
|
||||
.gl-p-5
|
||||
- if current_user.admin?
|
||||
.text-warning
|
||||
.gl-text-orange-500
|
||||
%p
|
||||
= sprite_icon('warning-solid')
|
||||
= html_escape(_('You are an admin, which means granting access to %{client_name} will allow them to interact with GitLab as an admin as well. Proceed with caution.')) % { client_name: tag.strong(@pre_auth.client.name) }
|
||||
|
@ -27,25 +27,25 @@
|
|||
- @pre_auth.scopes.each do |scope|
|
||||
%li
|
||||
%strong= t scope, scope: [:doorkeeper, :scopes]
|
||||
.text-secondary= t scope, scope: [:doorkeeper, :scope_desc]
|
||||
.form-actions.text-right
|
||||
= form_tag oauth_authorization_path, method: :delete, class: 'inline' do
|
||||
= hidden_field_tag :client_id, @pre_auth.client.uid
|
||||
= hidden_field_tag :redirect_uri, @pre_auth.redirect_uri
|
||||
= hidden_field_tag :state, @pre_auth.state
|
||||
= hidden_field_tag :response_type, @pre_auth.response_type
|
||||
= hidden_field_tag :scope, @pre_auth.scope
|
||||
= hidden_field_tag :nonce, @pre_auth.nonce
|
||||
= hidden_field_tag :code_challenge, @pre_auth.code_challenge
|
||||
= hidden_field_tag :code_challenge_method, @pre_auth.code_challenge_method
|
||||
= submit_tag _("Deny"), class: "gl-button btn btn-danger"
|
||||
= form_tag oauth_authorization_path, method: :post, class: 'inline' do
|
||||
= hidden_field_tag :client_id, @pre_auth.client.uid
|
||||
= hidden_field_tag :redirect_uri, @pre_auth.redirect_uri
|
||||
= hidden_field_tag :state, @pre_auth.state
|
||||
= hidden_field_tag :response_type, @pre_auth.response_type
|
||||
= hidden_field_tag :scope, @pre_auth.scope
|
||||
= hidden_field_tag :nonce, @pre_auth.nonce
|
||||
= hidden_field_tag :code_challenge, @pre_auth.code_challenge
|
||||
= hidden_field_tag :code_challenge_method, @pre_auth.code_challenge_method
|
||||
= submit_tag _("Authorize"), class: "gl-button btn btn-confirm gl-ml-3", data: { qa_selector: 'authorization_button' }
|
||||
.gl-text-gray-500= t scope, scope: [:doorkeeper, :scope_desc]
|
||||
.gl-p-5.gl-bg-gray-10.gl-border-t-gray-200.gl-border-t-1.gl-border-t-solid.gl-rounded-bottom-right-base.gl-rounded-bottom-left-base.gl-text-right
|
||||
= form_tag oauth_authorization_path, method: :delete, class: 'inline' do
|
||||
= hidden_field_tag :client_id, @pre_auth.client.uid
|
||||
= hidden_field_tag :redirect_uri, @pre_auth.redirect_uri
|
||||
= hidden_field_tag :state, @pre_auth.state
|
||||
= hidden_field_tag :response_type, @pre_auth.response_type
|
||||
= hidden_field_tag :scope, @pre_auth.scope
|
||||
= hidden_field_tag :nonce, @pre_auth.nonce
|
||||
= hidden_field_tag :code_challenge, @pre_auth.code_challenge
|
||||
= hidden_field_tag :code_challenge_method, @pre_auth.code_challenge_method
|
||||
= submit_tag _("Deny"), class: "btn btn-default gl-button"
|
||||
= form_tag oauth_authorization_path, method: :post, class: 'inline' do
|
||||
= hidden_field_tag :client_id, @pre_auth.client.uid
|
||||
= hidden_field_tag :redirect_uri, @pre_auth.redirect_uri
|
||||
= hidden_field_tag :state, @pre_auth.state
|
||||
= hidden_field_tag :response_type, @pre_auth.response_type
|
||||
= hidden_field_tag :scope, @pre_auth.scope
|
||||
= hidden_field_tag :nonce, @pre_auth.nonce
|
||||
= hidden_field_tag :code_challenge, @pre_auth.code_challenge
|
||||
= hidden_field_tag :code_challenge_method, @pre_auth.code_challenge_method
|
||||
= submit_tag _("Authorize"), class: "btn btn-danger gl-button gl-ml-3", data: { qa_selector: 'authorization_button' }
|
||||
|
|
|
@ -94,8 +94,7 @@
|
|||
= s_('Preferences|Surround text selection when typing quotes or brackets')
|
||||
.form-text.text-muted
|
||||
- supported_characters = %w(" ' ` \( [ { < * _).map {|char| "<code>#{char}</code>" }.join(', ')
|
||||
- msg = "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: #{supported_characters}."
|
||||
= s_(msg).html_safe
|
||||
= sprintf(s_( "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."), { supported_characters: supported_characters }).html_safe
|
||||
|
||||
.form-group
|
||||
= f.label :tab_width, s_('Preferences|Tab width'), class: 'label-bold'
|
||||
|
|
|
@ -18,7 +18,7 @@ module Metrics
|
|||
dashboard_paths = ::Gitlab::Metrics::Dashboard::RepoDashboardFinder.list_dashboards(project)
|
||||
|
||||
dashboard_paths.each do |dashboard_path|
|
||||
::Gitlab::Metrics::Dashboard::Importer.new(dashboard_path, project).execute!
|
||||
::Gitlab::Metrics::Dashboard::Importer.new(dashboard_path, project).execute
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -11,7 +11,7 @@ module Db
|
|||
name: FFaker::Name.name,
|
||||
email: FFaker::Internet.email,
|
||||
confirmed_at: DateTime.now,
|
||||
password: '12345678'
|
||||
password: Gitlab::Password.test_default
|
||||
)
|
||||
|
||||
::AbuseReport.create(reporter: ::User.take, user: reported_user, message: 'User sends spam')
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class RemoveCiPipelinesLockVersionIndex < Gitlab::Database::Migration[1.0]
|
||||
TABLE = :ci_pipelines
|
||||
INDEX_NAME = 'tmp_index_ci_pipelines_lock_version'
|
||||
COLUMN = :id
|
||||
|
||||
disable_ddl_transaction!
|
||||
|
||||
def up
|
||||
remove_concurrent_index TABLE, COLUMN, where: "lock_version IS NULL", name: INDEX_NAME
|
||||
end
|
||||
|
||||
def down
|
||||
add_concurrent_index TABLE, COLUMN, where: "lock_version IS NULL", name: INDEX_NAME
|
||||
end
|
||||
end
|
|
@ -0,0 +1,17 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class RemoveForeignKeyCiRunnerNamespacesNamespaceId < Gitlab::Database::Migration[1.0]
|
||||
disable_ddl_transaction!
|
||||
|
||||
CONSTRAINT_NAME = 'fk_rails_f9d9ed3308'
|
||||
|
||||
def up
|
||||
with_lock_retries do
|
||||
remove_foreign_key_if_exists(:ci_runner_namespaces, :namespaces, name: CONSTRAINT_NAME)
|
||||
end
|
||||
end
|
||||
|
||||
def down
|
||||
add_concurrent_foreign_key :ci_runner_namespaces, :namespaces, column: :namespace_id, on_delete: :cascade, name: CONSTRAINT_NAME
|
||||
end
|
||||
end
|
|
@ -0,0 +1 @@
|
|||
34f966723cae63e831f7fc9d965cda90f1fd7bca522fc58e78a0de4b959a47a2
|
|
@ -0,0 +1 @@
|
|||
192fc0b934c7d52e431a0ce7524a51beb24fa004a940e6b0675e36b0da143891
|
|
@ -31438,9 +31438,6 @@ ALTER TABLE ONLY merge_requests_closing_issues
|
|||
ALTER TABLE ONLY merge_trains
|
||||
ADD CONSTRAINT fk_rails_f90820cb08 FOREIGN KEY (pipeline_id) REFERENCES ci_pipelines(id) ON DELETE SET NULL;
|
||||
|
||||
ALTER TABLE ONLY ci_runner_namespaces
|
||||
ADD CONSTRAINT fk_rails_f9d9ed3308 FOREIGN KEY (namespace_id) REFERENCES namespaces(id) ON DELETE CASCADE;
|
||||
|
||||
ALTER TABLE ONLY banned_users
|
||||
ADD CONSTRAINT fk_rails_fa5bb598e5 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
|
||||
|
||||
|
|
|
@ -23,17 +23,17 @@ the data storage for pipeline builds remains almost the same since 2012. In
|
|||
ia separate database. Now we want to improve the architecture of GitLab CI/CD
|
||||
product to enable further scaling.
|
||||
|
||||
*Disclaimer: The following contain information related to upcoming products,
|
||||
features, and functionality.
|
||||
_Disclaimer: The following contains information related to upcoming products,
|
||||
features, and functionality._
|
||||
|
||||
It is important to note that the information presented is for informational
|
||||
_It is important to note that the information presented is for informational
|
||||
purposes only. Please do not rely on this information for purchasing or
|
||||
planning purposes.
|
||||
planning purposes._
|
||||
|
||||
As with all projects, the items mentioned in this document and linked pages are
|
||||
_As with all projects, the items mentioned in this document and linked pages are
|
||||
subject to change or delay. The development, release and timing of any
|
||||
products, features, or functionality remain at the sole discretion of GitLab
|
||||
Inc.*
|
||||
Inc._
|
||||
|
||||
## Goals
|
||||
|
||||
|
|
|
@ -166,7 +166,7 @@ deploy_prod:
|
|||
|
||||
The `when: manual` action:
|
||||
|
||||
- Exposes a play button for the job in the GitLab UI.
|
||||
- Exposes a play button for the job in the GitLab UI, with the text **Can be manually deployed to <environment>**.
|
||||
- Means the `deploy_prod` job is only triggered when the play button is clicked.
|
||||
|
||||
You can find the play button in the pipelines, environments, deployments, and jobs views.
|
||||
|
|
|
@ -171,6 +171,7 @@ Each feature flag is defined in a separate YAML file consisting of a number of f
|
|||
| `default_enabled` | yes | The default state of the feature flag that is strictly validated, with `default_enabled:` passed as an argument. |
|
||||
| `introduced_by_url` | no | The URL to the Merge Request that introduced the feature flag. |
|
||||
| `rollout_issue_url` | no | The URL to the Issue covering the feature flag rollout. |
|
||||
| `milestone` | no | Milestone in which the feature was added. |
|
||||
| `group` | no | The [group](https://about.gitlab.com/handbook/product/categories/#devops-stages) that owns the feature flag. |
|
||||
|
||||
NOTE:
|
||||
|
|
|
@ -7,8 +7,8 @@ info: To determine the technical writer assigned to the Stage/Group associated w
|
|||
# Geo (development) **(PREMIUM SELF)**
|
||||
|
||||
Geo connects GitLab instances together. One GitLab instance is
|
||||
designated as a **primary** node and can be run with multiple
|
||||
**secondary** nodes. Geo orchestrates quite a few components that can be seen on
|
||||
designated as a **primary** site and can be run with multiple
|
||||
**secondary** sites. Geo orchestrates quite a few components that can be seen on
|
||||
the diagram below and are described in more detail within this document.
|
||||
|
||||
![Geo Architecture Diagram](../administration/geo/replication/img/geo_architecture.png)
|
||||
|
@ -22,16 +22,16 @@ Geo handles replication for different components:
|
|||
- [Uploaded blobs](#uploads-replication): includes anything from images attached on issues
|
||||
to raw logs and assets from CI.
|
||||
|
||||
With the exception of the Database replication, on a *secondary* node, everything is coordinated
|
||||
With the exception of the Database replication, on a *secondary* site, everything is coordinated
|
||||
by the [Geo Log Cursor](#geo-log-cursor).
|
||||
|
||||
### Geo Log Cursor daemon
|
||||
|
||||
The [Geo Log Cursor daemon](#geo-log-cursor-daemon) is a separate process running on
|
||||
each **secondary** node. It monitors the [Geo Event Log](#geo-event-log)
|
||||
each **secondary** site. It monitors the [Geo Event Log](#geo-event-log)
|
||||
for new events and creates background jobs for each specific event type.
|
||||
|
||||
For example when a repository is updated, the Geo **primary** node creates
|
||||
For example when a repository is updated, the Geo **primary** site creates
|
||||
a Geo event with an associated repository updated event. The Geo Log Cursor daemon
|
||||
picks the event up and schedules a `Geo::ProjectSyncWorker` job which will
|
||||
use the `Geo::RepositorySyncService` and `Geo::WikiSyncService` classes
|
||||
|
@ -41,7 +41,7 @@ The Geo Log Cursor daemon can operate in High Availability mode automatically.
|
|||
The daemon will try to acquire a lock from time to time and once acquired, it
|
||||
will behave as the *active* daemon.
|
||||
|
||||
Any additional running daemons on the same node, will be in standby
|
||||
Any additional running daemons on the same site, will be in standby
|
||||
mode, ready to resume work if the *active* daemon releases its lock.
|
||||
|
||||
We use the [`ExclusiveLease`](https://www.rubydoc.info/github/gitlabhq/gitlabhq/Gitlab/ExclusiveLease) lock type with a small TTL, that is renewed at every
|
||||
|
@ -53,14 +53,14 @@ the lock, it switches to standby mode.
|
|||
### Database replication
|
||||
|
||||
Geo uses [streaming replication](#streaming-replication) to replicate
|
||||
the database from the **primary** to the **secondary** nodes. This
|
||||
replication gives the **secondary** nodes access to all the data saved
|
||||
the database from the **primary** to the **secondary** sites. This
|
||||
replication gives the **secondary** sites access to all the data saved
|
||||
in the database. So users can log in on the **secondary** and read all
|
||||
the issues, merge requests, and so on, on the **secondary** node.
|
||||
the issues, merge requests, and so on, on the **secondary** site.
|
||||
|
||||
### Repository replication
|
||||
|
||||
Geo also replicates repositories. Each **secondary** node keeps track of
|
||||
Geo also replicates repositories. Each **secondary** site keeps track of
|
||||
the state of every repository in the [tracking database](#tracking-database).
|
||||
|
||||
There are a few ways a repository gets replicated by the:
|
||||
|
@ -92,7 +92,7 @@ background and it searches the `Geo::ProjectRegistry` model for
|
|||
projects that need updating. Those projects can be:
|
||||
|
||||
- Unsynced: Projects that have never been synced on the **secondary**
|
||||
node and so do not exist yet.
|
||||
site and so do not exist yet.
|
||||
- Updated recently: Projects that have a `last_repository_updated_at`
|
||||
timestamp that is more recent than the `last_repository_successful_sync_at`
|
||||
timestamp in the `Geo::ProjectRegistry` model.
|
||||
|
@ -106,7 +106,7 @@ it's successful, we replace the main repository with the newly cloned one.
|
|||
|
||||
### Uploads replication
|
||||
|
||||
File uploads are also being replicated to the **secondary** node. To
|
||||
File uploads are also being replicated to the **secondary** site. To
|
||||
track the state of syncing, the `Geo::UploadRegistry` model is used.
|
||||
|
||||
#### Upload Registry
|
||||
|
@ -123,7 +123,7 @@ models respectively.
|
|||
Also similar to the [Repository Sync worker](#repository-sync-worker),
|
||||
there is a `Geo::FileDownloadDispatchWorker` class that is run
|
||||
periodically to sync all uploads that aren't synced to the Geo
|
||||
**secondary** node yet.
|
||||
**secondary** site yet.
|
||||
|
||||
Files are copied via HTTP(s) and initiated via the
|
||||
`/api/v4/geo/transfers/:type/:id` endpoint,
|
||||
|
@ -136,18 +136,18 @@ To authenticate file transfers, each `GeoNode` record has two fields:
|
|||
- A public access key (`access_key` field).
|
||||
- A secret access key (`secret_access_key` field).
|
||||
|
||||
The **secondary** node authenticates itself via a [JWT request](https://jwt.io/).
|
||||
When the **secondary** node wishes to download a file, it sends an
|
||||
The **secondary** site authenticates itself via a [JWT request](https://jwt.io/).
|
||||
When the **secondary** site wishes to download a file, it sends an
|
||||
HTTP request with the `Authorization` header:
|
||||
|
||||
```plaintext
|
||||
Authorization: GL-Geo <access_key>:<JWT payload>
|
||||
```
|
||||
|
||||
The **primary** node uses the `access_key` field to look up the
|
||||
corresponding **secondary** node and decrypts the JWT payload,
|
||||
The **primary** site uses the `access_key` field to look up the
|
||||
corresponding **secondary** site and decrypts the JWT payload,
|
||||
which contains additional information to identify the file
|
||||
request. This ensures that the **secondary** node downloads the right
|
||||
request. This ensures that the **secondary** site downloads the right
|
||||
file for the right database ID. For example, for an LFS object, the
|
||||
request must also include the SHA256 sum of the file. An example JWT
|
||||
payload looks like:
|
||||
|
@ -157,7 +157,7 @@ payload looks like:
|
|||
```
|
||||
|
||||
If the requested file matches the requested SHA256 sum, then the Geo
|
||||
**primary** node sends data via the [X-Sendfile](https://www.nginx.com/resources/wiki/start/topics/examples/xsendfile/)
|
||||
**primary** site sends data via the [X-Sendfile](https://www.nginx.com/resources/wiki/start/topics/examples/xsendfile/)
|
||||
feature, which allows NGINX to handle the file transfer without tying
|
||||
up Rails or Workhorse.
|
||||
|
||||
|
@ -168,34 +168,34 @@ involved, otherwise it may fail with an encryption error.
|
|||
## Git Push to Geo secondary
|
||||
|
||||
The Git Push Proxy exists as a functionality built inside the `gitlab-shell` component.
|
||||
It is active on a **secondary** node only. It allows the user that has cloned a repository
|
||||
from the secondary node to push to the same URL.
|
||||
It is active on a **secondary** site only. It allows the user that has cloned a repository
|
||||
from the secondary site to push to the same URL.
|
||||
|
||||
Git `push` requests directed to a **secondary** node will be sent over to the **primary** node,
|
||||
while `pull` requests will continue to be served by the **secondary** node for maximum efficiency.
|
||||
Git `push` requests directed to a **secondary** site will be sent over to the **primary** site,
|
||||
while `pull` requests will continue to be served by the **secondary** site for maximum efficiency.
|
||||
|
||||
HTTPS and SSH requests are handled differently:
|
||||
|
||||
- With HTTPS, we will give the user a `HTTP 302 Redirect` pointing to the project on the **primary** node.
|
||||
- With HTTPS, we will give the user a `HTTP 302 Redirect` pointing to the project on the **primary** site.
|
||||
The Git client is wise enough to understand that status code and process the redirection.
|
||||
- With SSH, because there is no equivalent way to perform a redirect, we have to proxy the request.
|
||||
This is done inside [`gitlab-shell`](https://gitlab.com/gitlab-org/gitlab-shell), by first translating the request
|
||||
to the HTTP protocol, and then proxying it to the **primary** node.
|
||||
to the HTTP protocol, and then proxying it to the **primary** site.
|
||||
|
||||
The [`gitlab-shell`](https://gitlab.com/gitlab-org/gitlab-shell) daemon knows when to proxy based on the response
|
||||
from `/api/v4/allowed`. A special `HTTP 300` status code is returned and we execute a "custom action",
|
||||
specified in the response body. The response contains additional data that allows the proxied `push` operation
|
||||
to happen on the **primary** node.
|
||||
to happen on the **primary** site.
|
||||
|
||||
## Using the Tracking Database
|
||||
|
||||
Along with the main database that is replicated, a Geo **secondary**
|
||||
node has its own separate [Tracking database](#tracking-database).
|
||||
site has its own separate [Tracking database](#tracking-database).
|
||||
|
||||
The tracking database contains the state of the **secondary** node.
|
||||
The tracking database contains the state of the **secondary** site.
|
||||
|
||||
Any database migration that needs to be run as part of an upgrade
|
||||
needs to be applied to the tracking database on each **secondary** node.
|
||||
needs to be applied to the tracking database on each **secondary** site.
|
||||
|
||||
### Configuration
|
||||
|
||||
|
@ -223,12 +223,12 @@ projects/attachments/ and so on, in the tracking database and main database.
|
|||
|
||||
## Redis
|
||||
|
||||
Redis on the **secondary** node works the same as on the **primary**
|
||||
node. It is used for caching, storing sessions, and other persistent
|
||||
Redis on the **secondary** site works the same as on the **primary**
|
||||
site. It is used for caching, storing sessions, and other persistent
|
||||
data.
|
||||
|
||||
Redis data replication between **primary** and **secondary** node is
|
||||
not used, so sessions and so on, aren't shared between nodes.
|
||||
Redis data replication between **primary** and **secondary** site is
|
||||
not used, so sessions and so on, aren't shared between sites.
|
||||
|
||||
## Object Storage
|
||||
|
||||
|
@ -244,7 +244,7 @@ ignores items in object storage. Either:
|
|||
|
||||
- The object storage layer should take care of its own geographical
|
||||
replication.
|
||||
- All secondary nodes should use the same storage node.
|
||||
- All secondary sites should use the same storage site.
|
||||
|
||||
## Verification
|
||||
|
||||
|
@ -252,29 +252,29 @@ ignores items in object storage. Either:
|
|||
|
||||
Repositories are verified with a checksum.
|
||||
|
||||
The **primary** node calculates a checksum on the repository. It
|
||||
The **primary** site calculates a checksum on the repository. It
|
||||
basically hashes all Git refs together and stores that hash in the
|
||||
`project_repository_states` table of the database.
|
||||
|
||||
The **secondary** node does the same to calculate the hash of its
|
||||
clone, and compares the hash with the value the **primary** node
|
||||
The **secondary** site does the same to calculate the hash of its
|
||||
clone, and compares the hash with the value the **primary** site
|
||||
calculated. If there is a mismatch, Geo will mark this as a mismatch
|
||||
and the administrator can see this in the [Geo admin panel](../user/admin_area/geo_nodes.md).
|
||||
|
||||
## Glossary
|
||||
|
||||
### Primary node
|
||||
### Primary site
|
||||
|
||||
A **primary** node is the single node in a Geo setup that read-write
|
||||
A **primary** site is the single site in a Geo setup that read-write
|
||||
capabilities. It's the single source of truth and the Geo
|
||||
**secondary** nodes replicate their data from there.
|
||||
**secondary** sites replicate their data from there.
|
||||
|
||||
In a Geo setup, there can only be one **primary** node. All
|
||||
**secondary** nodes connect to that **primary**.
|
||||
In a Geo setup, there can only be one **primary** site. All
|
||||
**secondary** sites connect to that **primary**.
|
||||
|
||||
### Secondary node
|
||||
### Secondary site
|
||||
|
||||
A **secondary** node is a read-only replica of the **primary** node
|
||||
A **secondary** site is a read-only replica of the **primary** site
|
||||
running in a different geographical location.
|
||||
|
||||
### Streaming replication
|
||||
|
@ -287,11 +287,11 @@ Streaming replication depends on the Write Ahead Logs, or WAL. Those
|
|||
logs are copied over to the replica and replayed there.
|
||||
|
||||
Since streaming replication also replicates the schema, the database
|
||||
migration do not need to run on the secondary nodes.
|
||||
migration do not need to run on the secondary sites.
|
||||
|
||||
### Tracking database
|
||||
|
||||
A database on each Geo **secondary** node that keeps state for the node
|
||||
A database on each Geo **secondary** site that keeps state for the site
|
||||
on which it resides. Read more in [Using the Tracking database](#using-the-tracking-database).
|
||||
|
||||
## Geo Event Log
|
||||
|
@ -312,7 +312,7 @@ events include:
|
|||
|
||||
### Geo Log Cursor
|
||||
|
||||
The process running on the **secondary** node that looks for new
|
||||
The process running on the **secondary** site that looks for new
|
||||
`Geo::EventLog` rows.
|
||||
|
||||
## Code features
|
||||
|
@ -327,51 +327,51 @@ Many of these methods are cached using the `RequestStore` class, to
|
|||
reduce the performance impact of using the methods throughout the
|
||||
codebase.
|
||||
|
||||
#### Current node
|
||||
#### Current site
|
||||
|
||||
The class method `.current_node` returns the `GeoNode` record for the
|
||||
current node.
|
||||
current site.
|
||||
|
||||
We use the `host`, `port`, and `relative_url_root` values from
|
||||
`gitlab.yml` and search in the database to identify which node we are
|
||||
`gitlab.yml` and search in the database to identify which site we are
|
||||
in (see `GeoNode.current_node`).
|
||||
|
||||
#### Primary or secondary
|
||||
|
||||
To determine whether the current node is a **primary** node or a
|
||||
**secondary** node use the `.primary?` and `.secondary?` class
|
||||
To determine whether the current site is a **primary** site or a
|
||||
**secondary** site use the `.primary?` and `.secondary?` class
|
||||
methods.
|
||||
|
||||
It is possible for these methods to both return `false` on a node when
|
||||
the node is not enabled. See [Enablement](#enablement).
|
||||
It is possible for these methods to both return `false` on a site when
|
||||
the site is not enabled. See [Enablement](#enablement).
|
||||
|
||||
#### Geo Database configured?
|
||||
|
||||
There is also an additional gotcha when dealing with things that
|
||||
happen during initialization time. In a few places, we use the
|
||||
`Gitlab::Geo.geo_database_configured?` method to check if the node has
|
||||
`Gitlab::Geo.geo_database_configured?` method to check if the site has
|
||||
the tracking database, which only exists on the **secondary**
|
||||
node. This overcomes race conditions that could happen during
|
||||
bootstrapping of a new node.
|
||||
site. This overcomes race conditions that could happen during
|
||||
bootstrapping of a new site.
|
||||
|
||||
#### Enablement
|
||||
|
||||
We consider Geo feature enabled when the user has a valid license with the
|
||||
feature included, and they have at least one node defined at the Geo Nodes
|
||||
feature included, and they have at least one site defined at the Geo Nodes
|
||||
screen.
|
||||
|
||||
See `Gitlab::Geo.enabled?` and `Gitlab::Geo.license_allows?` methods.
|
||||
|
||||
#### Read-only
|
||||
|
||||
All Geo **secondary** nodes are read-only.
|
||||
All Geo **secondary** sites are read-only.
|
||||
|
||||
The general principle of a [read-only database](verifying_database_capabilities.md#read-only-database)
|
||||
applies to all Geo **secondary** nodes. So the
|
||||
applies to all Geo **secondary** sites. So the
|
||||
`Gitlab::Database.read_only?` method will always return `true` on a
|
||||
**secondary** node.
|
||||
**secondary** site.
|
||||
|
||||
When some write actions are not allowed because the node is a
|
||||
When some write actions are not allowed because the site is a
|
||||
**secondary**, consider adding the `Gitlab::Database.read_only?` or
|
||||
`Gitlab::Database.read_write?` guard, instead of `Gitlab::Geo.secondary?`.
|
||||
|
||||
|
@ -393,7 +393,7 @@ that need to be taken care of:
|
|||
- Verification.
|
||||
- Cleaner. When sync settings are changed for the secondary site, some resources need to be cleaned up.
|
||||
- Geo Node Status. We need to provide API endpoints as well as some presentation in the GitLab Admin Area.
|
||||
- Health Check. If we can perform some pre-cheсks and make node unhealthy if something is wrong, we should do that.
|
||||
- Health Check. If we can perform some pre-cheсks and make site unhealthy if something is wrong, we should do that.
|
||||
The `rake gitlab:geo:check` command has to be updated too.
|
||||
|
||||
## History of communication channel
|
||||
|
@ -404,7 +404,7 @@ check here historic decisions and why we moved to new implementations.
|
|||
### Custom code (GitLab 8.6 and earlier)
|
||||
|
||||
In GitLab versions before 8.6, custom code is used to handle
|
||||
notification from **primary** node to **secondary** nodes by HTTP
|
||||
notification from **primary** site to **secondary** sites by HTTP
|
||||
requests.
|
||||
|
||||
### System hooks (GitLab 8.7 to 9.5)
|
||||
|
|
|
@ -14,7 +14,7 @@ team to discuss the options. You can contact them in `#g_geo` on Slack
|
|||
or mention `@geo-team` in the issue or merge request.
|
||||
|
||||
Geo provides an API to make it possible to easily replicate data types
|
||||
across Geo nodes. This API is presented as a Ruby Domain-Specific
|
||||
across Geo sites. This API is presented as a Ruby Domain-Specific
|
||||
Language (DSL) and aims to make it possible to replicate data with
|
||||
minimal effort of the engineer who created a data type.
|
||||
|
||||
|
@ -43,7 +43,7 @@ naming conventions:
|
|||
For more detail, see [Data types](../../administration/geo/replication/datatypes.md).
|
||||
|
||||
- **Geo Replicable**:
|
||||
A Replicable is a resource Geo wants to sync across Geo nodes. There
|
||||
A Replicable is a resource Geo wants to sync across Geo sites. There
|
||||
is a limited set of supported data types of replicables. The effort
|
||||
required to implement replication of a resource that belongs to one
|
||||
of the known data types is minimal.
|
||||
|
@ -57,7 +57,7 @@ naming conventions:
|
|||
It's tied to the Geo Replicable data type. All replicators have a
|
||||
common interface that can be used to process (that is, produce and
|
||||
consume) events. It takes care of the communication between the
|
||||
primary node (where events are produced) and the secondary node
|
||||
primary site (where events are produced) and the secondary site
|
||||
(where events are consumed). The engineer who wants to incorporate
|
||||
Geo in their feature will use the API of replicators to make this
|
||||
happen.
|
||||
|
|
|
@ -230,8 +230,8 @@ module Gitlab
|
|||
name: name.strip.presence || valid_username,
|
||||
username: valid_username,
|
||||
email: email,
|
||||
password: auth_hash.password,
|
||||
password_confirmation: auth_hash.password,
|
||||
password: Gitlab::Password.test_default(21),
|
||||
password_confirmation: Gitlab::Password.test_default(21),
|
||||
password_automatically_set: true
|
||||
}
|
||||
end
|
||||
|
|
|
@ -1,3 +1,11 @@
|
|||
dast_site_profiles_pipelines:
|
||||
- table: ci_pipelines
|
||||
column: ci_pipeline_id
|
||||
on_delete: async_delete
|
||||
vulnerability_feedback:
|
||||
- table: ci_pipelines
|
||||
column: pipeline_id
|
||||
on_delete: async_nullify
|
||||
ci_pipeline_chat_data:
|
||||
- table: chat_names
|
||||
column: chat_name_id
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
# This module is used to return fake strong password for tests
|
||||
|
||||
module Gitlab
|
||||
module Password
|
||||
DEFAULT_LENGTH = 12
|
||||
TEST_DEFAULT = "123qweQWE!@#" + "0" * (User.password_length.max - DEFAULT_LENGTH)
|
||||
def self.test_default(length = 12)
|
||||
password_length = [[User.password_length.min, length].max, User.password_length.max].min
|
||||
TEST_DEFAULT[...password_length]
|
||||
end
|
||||
end
|
||||
end
|
|
@ -125,7 +125,7 @@ class GroupSeeder
|
|||
name: FFaker::Name.name,
|
||||
email: FFaker::Internet.email,
|
||||
confirmed_at: DateTime.now,
|
||||
password: Devise.friendly_token
|
||||
password: Gitlab::Password.test_default
|
||||
)
|
||||
end
|
||||
|
||||
|
|
|
@ -26863,6 +26863,9 @@ msgstr ""
|
|||
msgid "Preferences|Use relative times"
|
||||
msgstr ""
|
||||
|
||||
msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
|
||||
msgstr ""
|
||||
|
||||
msgid "Prev"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -11,9 +11,8 @@ module RuboCop
|
|||
ENFORCED_SINCE = 2020_02_12_00_00_00
|
||||
|
||||
MSG = <<~MSG
|
||||
Don't call the background migration worker directly, use the `#migrate_async`,
|
||||
`#migrate_in`, `#bulk_migrate_async` or `#bulk_migrate_in` migration helpers
|
||||
instead.
|
||||
Don't call the background migration worker directly, use the `#migrate_in` or
|
||||
`#queue_background_migration_jobs_by_range_at_intervals` migration helpers instead.
|
||||
MSG
|
||||
|
||||
def_node_matcher :calls_background_migration_worker?, <<~PATTERN
|
||||
|
@ -26,28 +25,6 @@ module RuboCop
|
|||
|
||||
add_offense(node, location: :expression) if calls_background_migration_worker?(node)
|
||||
end
|
||||
|
||||
def autocorrect(node)
|
||||
# This gets rid of the receiver `BackgroundMigrationWorker` and
|
||||
# replaces `perform` with `schedule`
|
||||
schedule_method = method_name(node).to_s.sub('perform', 'migrate')
|
||||
arguments = arguments(node).map(&:source).join(', ')
|
||||
|
||||
replacement = "#{schedule_method}(#{arguments})"
|
||||
lambda do |corrector|
|
||||
corrector.replace(node.source_range, replacement)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def method_name(node)
|
||||
node.children.second
|
||||
end
|
||||
|
||||
def arguments(node)
|
||||
node.children[2..]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -612,8 +612,8 @@ RSpec.describe Admin::UsersController do
|
|||
end
|
||||
|
||||
context 'when the new password does not match the password confirmation' do
|
||||
let(:password) { 'some_password' }
|
||||
let(:password_confirmation) { 'not_same_as_password' }
|
||||
let(:password) { Gitlab::Password.test_default }
|
||||
let(:password_confirmation) { "not" + Gitlab::Password.test_default }
|
||||
|
||||
it 'shows the edit page again' do
|
||||
update_password(user, password, password_confirmation)
|
||||
|
|
|
@ -58,7 +58,7 @@ RSpec.describe Ldap::OmniauthCallbacksController do
|
|||
end
|
||||
|
||||
context 'sign up' do
|
||||
let(:user) { double(email: +'new@example.com') }
|
||||
let(:user) { create(:user) }
|
||||
|
||||
before do
|
||||
stub_omniauth_setting(block_auto_created_users: false)
|
||||
|
|
|
@ -483,7 +483,7 @@ RSpec.describe RegistrationsController do
|
|||
end
|
||||
|
||||
it 'succeeds if password is confirmed' do
|
||||
post :destroy, params: { password: '12345678' }
|
||||
post :destroy, params: { password: Gitlab::Password.test_default }
|
||||
|
||||
expect_success
|
||||
end
|
||||
|
@ -524,7 +524,7 @@ RSpec.describe RegistrationsController do
|
|||
end
|
||||
|
||||
it 'fails' do
|
||||
delete :destroy, params: { password: '12345678' }
|
||||
delete :destroy, params: { password: Gitlab::Password.test_default }
|
||||
|
||||
expect_failure(s_('Profiles|You must transfer ownership or delete groups you are an owner of before you can delete your account'))
|
||||
end
|
||||
|
|
|
@ -5,7 +5,7 @@ FactoryBot.define do
|
|||
email { generate(:email) }
|
||||
name { generate(:name) }
|
||||
username { generate(:username) }
|
||||
password { "12345678" }
|
||||
password { Gitlab::Password.test_default }
|
||||
role { 'software_developer' }
|
||||
confirmed_at { Time.now }
|
||||
confirmation_token { nil }
|
||||
|
|
|
@ -5,10 +5,11 @@ require 'spec_helper'
|
|||
RSpec.describe 'Dashboard Todos' do
|
||||
include DesignManagementTestHelpers
|
||||
|
||||
let_it_be(:user) { create(:user, username: 'john') }
|
||||
let_it_be(:author) { create(:user) }
|
||||
let_it_be(:user) { create(:user, username: 'john') }
|
||||
let_it_be(:user2) { create(:user, username: 'diane') }
|
||||
let_it_be(:author) { create(:user) }
|
||||
let_it_be(:project) { create(:project, :public) }
|
||||
let_it_be(:issue) { create(:issue, project: project, due_date: Date.today, title: "Fix bug") }
|
||||
let_it_be(:issue) { create(:issue, project: project, due_date: Date.today, title: "Fix bug") }
|
||||
|
||||
before_all do
|
||||
project.add_developer(user)
|
||||
|
@ -23,6 +24,19 @@ RSpec.describe 'Dashboard Todos' do
|
|||
it 'shows "All done" message' do
|
||||
expect(page).to have_content 'Your To-Do List shows what to work on next'
|
||||
end
|
||||
|
||||
context 'when user was assigned to an issue and marked it as done' do
|
||||
before do
|
||||
sign_in(user)
|
||||
end
|
||||
|
||||
it 'shows "Are you looking for things to do?" message' do
|
||||
create(:todo, :assigned, :done, user: user, project: project, target: issue, author: user2)
|
||||
visit dashboard_todos_path
|
||||
|
||||
expect(page).to have_content 'Are you looking for things to do? Take a look at open issues, contribute to a merge request, or mention someone in a comment to automatically assign them a new to-do item.'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the todo references a merge request' do
|
||||
|
|
|
@ -44,8 +44,8 @@ RSpec.describe 'Password reset' do
|
|||
|
||||
visit(edit_user_password_path(reset_password_token: token))
|
||||
|
||||
fill_in 'New password', with: 'hello1234'
|
||||
fill_in 'Confirm new password', with: 'hello1234'
|
||||
fill_in 'New password', with: "new" + Gitlab::Password.test_default
|
||||
fill_in 'Confirm new password', with: "new" + Gitlab::Password.test_default
|
||||
|
||||
click_button 'Change your password'
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ RSpec.describe 'Profile account page', :js do
|
|||
it 'deletes user', :js, :sidekiq_might_not_need_inline do
|
||||
click_button 'Delete account'
|
||||
|
||||
fill_in 'password', with: '12345678'
|
||||
fill_in 'password', with: Gitlab::Password.test_default
|
||||
|
||||
page.within '.modal' do
|
||||
click_button 'Delete account'
|
||||
|
|
|
@ -39,7 +39,7 @@ RSpec.describe 'Profile > Password' do
|
|||
|
||||
describe 'User puts the same passwords in the field and in the confirmation' do
|
||||
it 'shows a success message' do
|
||||
fill_passwords('mypassword', 'mypassword')
|
||||
fill_passwords(Gitlab::Password.test_default, Gitlab::Password.test_default)
|
||||
|
||||
page.within('.flash-notice') do
|
||||
expect(page).to have_content('Password was successfully updated. Please sign in again.')
|
||||
|
@ -79,7 +79,7 @@ RSpec.describe 'Profile > Password' do
|
|||
end
|
||||
|
||||
context 'Change password' do
|
||||
let(:new_password) { '22233344' }
|
||||
let(:new_password) { "new" + Gitlab::Password.test_default }
|
||||
|
||||
before do
|
||||
sign_in(user)
|
||||
|
@ -170,8 +170,8 @@ RSpec.describe 'Profile > Password' do
|
|||
expect(current_path).to eq new_profile_password_path
|
||||
|
||||
fill_in :user_password, with: user.password
|
||||
fill_in :user_new_password, with: '12345678'
|
||||
fill_in :user_password_confirmation, with: '12345678'
|
||||
fill_in :user_new_password, with: Gitlab::Password.test_default
|
||||
fill_in :user_password_confirmation, with: Gitlab::Password.test_default
|
||||
click_button 'Set new password'
|
||||
|
||||
expect(current_path).to eq new_user_session_path
|
||||
|
|
|
@ -9,7 +9,7 @@ RSpec.describe 'Session TTLs', :clean_gitlab_redis_shared_state do
|
|||
visit new_user_session_path
|
||||
# The session key only gets created after a post
|
||||
fill_in 'user_login', with: 'non-existant@gitlab.org'
|
||||
fill_in 'user_password', with: '12345678'
|
||||
fill_in 'user_password', with: Gitlab::Password.test_default
|
||||
click_button 'Sign in'
|
||||
|
||||
expect(page).to have_content('Invalid login or password')
|
||||
|
|
|
@ -49,15 +49,15 @@ RSpec.describe 'Login', :clean_gitlab_redis_sessions do
|
|||
expect(current_path).to eq edit_user_password_path
|
||||
expect(page).to have_content('Please create a password for your new account.')
|
||||
|
||||
fill_in 'user_password', with: 'password'
|
||||
fill_in 'user_password_confirmation', with: 'password'
|
||||
fill_in 'user_password', with: Gitlab::Password.test_default
|
||||
fill_in 'user_password_confirmation', with: Gitlab::Password.test_default
|
||||
click_button 'Change your password'
|
||||
|
||||
expect(current_path).to eq new_user_session_path
|
||||
expect(page).to have_content(I18n.t('devise.passwords.updated_not_active'))
|
||||
|
||||
fill_in 'user_login', with: user.username
|
||||
fill_in 'user_password', with: 'password'
|
||||
fill_in 'user_password', with: Gitlab::Password.test_default
|
||||
click_button 'Sign in'
|
||||
|
||||
expect_single_session_with_authenticated_ttl
|
||||
|
@ -210,7 +210,7 @@ RSpec.describe 'Login', :clean_gitlab_redis_sessions do
|
|||
end
|
||||
|
||||
it 'does not allow sign-in if the user password is updated before entering a one-time code' do
|
||||
user.update!(password: 'new_password')
|
||||
user.update!(password: "new" + Gitlab::Password.test_default)
|
||||
|
||||
enter_code(user.current_otp)
|
||||
|
||||
|
@ -447,7 +447,7 @@ RSpec.describe 'Login', :clean_gitlab_redis_sessions do
|
|||
visit new_user_session_path
|
||||
|
||||
fill_in 'user_login', with: user.email
|
||||
fill_in 'user_password', with: '12345678'
|
||||
fill_in 'user_password', with: Gitlab::Password.test_default
|
||||
click_button 'Sign in'
|
||||
|
||||
expect(current_path).to eq(new_profile_password_path)
|
||||
|
@ -456,7 +456,7 @@ RSpec.describe 'Login', :clean_gitlab_redis_sessions do
|
|||
end
|
||||
|
||||
context 'with invalid username and password' do
|
||||
let(:user) { create(:user, password: 'not-the-default') }
|
||||
let(:user) { create(:user, password: "not" + Gitlab::Password.test_default) }
|
||||
|
||||
it 'blocks invalid login' do
|
||||
expect(authentication_metrics)
|
||||
|
@ -767,7 +767,7 @@ RSpec.describe 'Login', :clean_gitlab_redis_sessions do
|
|||
visit new_user_session_path
|
||||
|
||||
fill_in 'user_login', with: user.email
|
||||
fill_in 'user_password', with: '12345678'
|
||||
fill_in 'user_password', with: Gitlab::Password.test_default
|
||||
|
||||
click_button 'Sign in'
|
||||
|
||||
|
@ -788,7 +788,7 @@ RSpec.describe 'Login', :clean_gitlab_redis_sessions do
|
|||
visit new_user_session_path
|
||||
|
||||
fill_in 'user_login', with: user.email
|
||||
fill_in 'user_password', with: '12345678'
|
||||
fill_in 'user_password', with: Gitlab::Password.test_default
|
||||
|
||||
click_button 'Sign in'
|
||||
|
||||
|
@ -809,7 +809,7 @@ RSpec.describe 'Login', :clean_gitlab_redis_sessions do
|
|||
visit new_user_session_path
|
||||
|
||||
fill_in 'user_login', with: user.email
|
||||
fill_in 'user_password', with: '12345678'
|
||||
fill_in 'user_password', with: Gitlab::Password.test_default
|
||||
|
||||
click_button 'Sign in'
|
||||
|
||||
|
@ -844,7 +844,7 @@ RSpec.describe 'Login', :clean_gitlab_redis_sessions do
|
|||
visit new_user_session_path
|
||||
|
||||
fill_in 'user_login', with: user.email
|
||||
fill_in 'user_password', with: '12345678'
|
||||
fill_in 'user_password', with: Gitlab::Password.test_default
|
||||
click_button 'Sign in'
|
||||
|
||||
fill_in 'user_otp_attempt', with: user.reload.current_otp
|
||||
|
@ -870,7 +870,7 @@ RSpec.describe 'Login', :clean_gitlab_redis_sessions do
|
|||
visit new_user_session_path
|
||||
|
||||
fill_in 'user_login', with: user.email
|
||||
fill_in 'user_password', with: '12345678'
|
||||
fill_in 'user_password', with: Gitlab::Password.test_default
|
||||
click_button 'Sign in'
|
||||
|
||||
expect_to_be_on_terms_page
|
||||
|
@ -878,7 +878,7 @@ RSpec.describe 'Login', :clean_gitlab_redis_sessions do
|
|||
|
||||
expect(current_path).to eq(new_profile_password_path)
|
||||
|
||||
fill_in 'user_password', with: '12345678'
|
||||
fill_in 'user_password', with: Gitlab::Password.test_default
|
||||
fill_in 'user_new_password', with: 'new password'
|
||||
fill_in 'user_password_confirmation', with: 'new password'
|
||||
click_button 'Set new password'
|
||||
|
|
|
@ -100,6 +100,7 @@ describe('GroupItemComponent', () => {
|
|||
wrapper.destroy();
|
||||
|
||||
group.type = 'project';
|
||||
group.lastActivityAt = '2017-04-09T18:40:39.101Z';
|
||||
wrapper = createComponent({ group });
|
||||
|
||||
expect(wrapper.vm.isGroup).toBe(false);
|
||||
|
|
|
@ -38,6 +38,7 @@ describe('ItemStats', () => {
|
|||
...mockParentGroupItem,
|
||||
type: ITEM_TYPE.PROJECT,
|
||||
starCount: 4,
|
||||
lastActivityAt: '2017-04-09T18:40:39.101Z',
|
||||
};
|
||||
|
||||
createComponent({ item });
|
||||
|
|
|
@ -3,7 +3,7 @@ import MockAdapter from 'axios-mock-adapter';
|
|||
import * as Sentry from '@sentry/browser';
|
||||
import { setHTMLFixture } from 'helpers/fixtures';
|
||||
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
|
||||
import { mockIntegrationProps } from 'jest/integrations/edit/mock_data';
|
||||
import waitForPromises from 'helpers/wait_for_promises';
|
||||
import ActiveCheckbox from '~/integrations/edit/components/active_checkbox.vue';
|
||||
import ConfirmationModal from '~/integrations/edit/components/confirmation_modal.vue';
|
||||
import DynamicField from '~/integrations/edit/components/dynamic_field.vue';
|
||||
|
@ -13,7 +13,6 @@ import JiraTriggerFields from '~/integrations/edit/components/jira_trigger_field
|
|||
import OverrideDropdown from '~/integrations/edit/components/override_dropdown.vue';
|
||||
import ResetConfirmationModal from '~/integrations/edit/components/reset_confirmation_modal.vue';
|
||||
import TriggerFields from '~/integrations/edit/components/trigger_fields.vue';
|
||||
import waitForPromises from 'helpers/wait_for_promises';
|
||||
import {
|
||||
integrationLevels,
|
||||
I18N_SUCCESSFUL_CONNECTION_MESSAGE,
|
||||
|
@ -23,9 +22,12 @@ import {
|
|||
import { createStore } from '~/integrations/edit/store';
|
||||
import eventHub from '~/integrations/edit/event_hub';
|
||||
import httpStatus from '~/lib/utils/http_status';
|
||||
import { refreshCurrentPage } from '~/lib/utils/url_utility';
|
||||
import { mockIntegrationProps } from '../mock_data';
|
||||
|
||||
jest.mock('~/integrations/edit/event_hub');
|
||||
jest.mock('@sentry/browser');
|
||||
jest.mock('~/lib/utils/url_utility');
|
||||
|
||||
describe('IntegrationForm', () => {
|
||||
const mockToastShow = jest.fn();
|
||||
|
@ -80,7 +82,8 @@ describe('IntegrationForm', () => {
|
|||
const findConfirmationModal = () => wrapper.findComponent(ConfirmationModal);
|
||||
const findResetConfirmationModal = () => wrapper.findComponent(ResetConfirmationModal);
|
||||
const findResetButton = () => wrapper.findByTestId('reset-button');
|
||||
const findSaveButton = () => wrapper.findByTestId('save-button');
|
||||
const findProjectSaveButton = () => wrapper.findByTestId('save-button');
|
||||
const findInstanceOrGroupSaveButton = () => wrapper.findByTestId('save-button-instance-group');
|
||||
const findTestButton = () => wrapper.findByTestId('test-button');
|
||||
const findJiraTriggerFields = () => wrapper.findComponent(JiraTriggerFields);
|
||||
const findJiraIssuesFields = () => wrapper.findComponent(JiraIssuesFields);
|
||||
|
@ -395,11 +398,11 @@ describe('IntegrationForm', () => {
|
|||
},
|
||||
});
|
||||
|
||||
await findSaveButton().vm.$emit('click', new Event('click'));
|
||||
await findProjectSaveButton().vm.$emit('click', new Event('click'));
|
||||
});
|
||||
|
||||
it('sets save button `loading` prop to `true`', () => {
|
||||
expect(findSaveButton().props('loading')).toBe(true);
|
||||
expect(findProjectSaveButton().props('loading')).toBe(true);
|
||||
});
|
||||
|
||||
it('sets test button `disabled` prop to `true`', () => {
|
||||
|
@ -425,7 +428,7 @@ describe('IntegrationForm', () => {
|
|||
},
|
||||
});
|
||||
|
||||
await findSaveButton().vm.$emit('click', new Event('click'));
|
||||
await findProjectSaveButton().vm.$emit('click', new Event('click'));
|
||||
});
|
||||
|
||||
it('submit form', () => {
|
||||
|
@ -445,7 +448,7 @@ describe('IntegrationForm', () => {
|
|||
},
|
||||
});
|
||||
|
||||
await findSaveButton().vm.$emit('click', new Event('click'));
|
||||
await findProjectSaveButton().vm.$emit('click', new Event('click'));
|
||||
});
|
||||
|
||||
it('does not submit form', () => {
|
||||
|
@ -453,7 +456,7 @@ describe('IntegrationForm', () => {
|
|||
});
|
||||
|
||||
it('sets save button `loading` prop to `false`', () => {
|
||||
expect(findSaveButton().props('loading')).toBe(false);
|
||||
expect(findProjectSaveButton().props('loading')).toBe(false);
|
||||
});
|
||||
|
||||
it('sets test button `disabled` prop to `false`', () => {
|
||||
|
@ -507,7 +510,7 @@ describe('IntegrationForm', () => {
|
|||
});
|
||||
|
||||
it('sets save button `disabled` prop to `true`', () => {
|
||||
expect(findSaveButton().props('disabled')).toBe(true);
|
||||
expect(findProjectSaveButton().props('disabled')).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -536,7 +539,7 @@ describe('IntegrationForm', () => {
|
|||
});
|
||||
|
||||
it('sets save button `disabled` prop to `false`', () => {
|
||||
expect(findSaveButton().props('disabled')).toBe(false);
|
||||
expect(findProjectSaveButton().props('disabled')).toBe(false);
|
||||
});
|
||||
|
||||
it(`${expectSentry ? 'does' : 'does not'} capture exception in Sentry`, () => {
|
||||
|
@ -545,4 +548,83 @@ describe('IntegrationForm', () => {
|
|||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('when `reset-confirmation-modal` emits `reset` event', () => {
|
||||
const mockResetPath = '/reset';
|
||||
|
||||
describe('buttons', () => {
|
||||
beforeEach(async () => {
|
||||
createComponent({
|
||||
customStateProps: {
|
||||
integrationLevel: integrationLevels.GROUP,
|
||||
canTest: true,
|
||||
resetPath: mockResetPath,
|
||||
},
|
||||
});
|
||||
|
||||
await findResetConfirmationModal().vm.$emit('reset');
|
||||
});
|
||||
|
||||
it('sets reset button `loading` prop to `true`', () => {
|
||||
expect(findResetButton().props('loading')).toBe(true);
|
||||
});
|
||||
|
||||
it('sets other button `disabled` props to `true`', () => {
|
||||
expect(findInstanceOrGroupSaveButton().props('disabled')).toBe(true);
|
||||
expect(findTestButton().props('disabled')).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when "reset settings" request fails', () => {
|
||||
beforeEach(async () => {
|
||||
mockAxios.onPost(mockResetPath).replyOnce(httpStatus.INTERNAL_SERVER_ERROR);
|
||||
createComponent({
|
||||
customStateProps: {
|
||||
integrationLevel: integrationLevels.GROUP,
|
||||
canTest: true,
|
||||
resetPath: mockResetPath,
|
||||
},
|
||||
});
|
||||
|
||||
await findResetConfirmationModal().vm.$emit('reset');
|
||||
await waitForPromises();
|
||||
});
|
||||
|
||||
it('displays a toast', () => {
|
||||
expect(mockToastShow).toHaveBeenCalledWith(I18N_DEFAULT_ERROR_MESSAGE);
|
||||
});
|
||||
|
||||
it('captures exception in Sentry', () => {
|
||||
expect(Sentry.captureException).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('sets reset button `loading` prop to `false`', () => {
|
||||
expect(findResetButton().props('loading')).toBe(false);
|
||||
});
|
||||
|
||||
it('sets button `disabled` props to `false`', () => {
|
||||
expect(findInstanceOrGroupSaveButton().props('disabled')).toBe(false);
|
||||
expect(findTestButton().props('disabled')).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when "reset settings" succeeds', () => {
|
||||
beforeEach(async () => {
|
||||
mockAxios.onPost(mockResetPath).replyOnce(httpStatus.OK);
|
||||
createComponent({
|
||||
customStateProps: {
|
||||
integrationLevel: integrationLevels.GROUP,
|
||||
resetPath: mockResetPath,
|
||||
},
|
||||
});
|
||||
|
||||
await findResetConfirmationModal().vm.$emit('reset');
|
||||
await waitForPromises();
|
||||
});
|
||||
|
||||
it('calls `refreshCurrentPage`', () => {
|
||||
expect(refreshCurrentPage).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -4,17 +4,12 @@ import testAction from 'helpers/vuex_action_helper';
|
|||
import { I18N_FETCH_TEST_SETTINGS_DEFAULT_ERROR_MESSAGE } from '~/integrations/constants';
|
||||
import {
|
||||
setOverride,
|
||||
setIsResetting,
|
||||
requestResetIntegration,
|
||||
receiveResetIntegrationSuccess,
|
||||
receiveResetIntegrationError,
|
||||
requestJiraIssueTypes,
|
||||
receiveJiraIssueTypesSuccess,
|
||||
receiveJiraIssueTypesError,
|
||||
} from '~/integrations/edit/store/actions';
|
||||
import * as types from '~/integrations/edit/store/mutation_types';
|
||||
import createState from '~/integrations/edit/store/state';
|
||||
import { refreshCurrentPage } from '~/lib/utils/url_utility';
|
||||
import { mockJiraIssueTypes } from '../mock_data';
|
||||
|
||||
jest.mock('~/lib/utils/url_utility');
|
||||
|
@ -38,38 +33,6 @@ describe('Integration form store actions', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('setIsResetting', () => {
|
||||
it('should commit isResetting mutation', () => {
|
||||
return testAction(setIsResetting, true, state, [
|
||||
{ type: types.SET_IS_RESETTING, payload: true },
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('requestResetIntegration', () => {
|
||||
it('should commit REQUEST_RESET_INTEGRATION mutation', () => {
|
||||
return testAction(requestResetIntegration, null, state, [
|
||||
{ type: types.REQUEST_RESET_INTEGRATION },
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('receiveResetIntegrationSuccess', () => {
|
||||
it('should call refreshCurrentPage()', () => {
|
||||
return testAction(receiveResetIntegrationSuccess, null, state, [], [], () => {
|
||||
expect(refreshCurrentPage).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('receiveResetIntegrationError', () => {
|
||||
it('should commit RECEIVE_RESET_INTEGRATION_ERROR mutation', () => {
|
||||
return testAction(receiveResetIntegrationError, null, state, [
|
||||
{ type: types.RECEIVE_RESET_INTEGRATION_ERROR },
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('requestJiraIssueTypes', () => {
|
||||
describe.each`
|
||||
scenario | responseCode | response | action
|
||||
|
|
|
@ -17,30 +17,6 @@ describe('Integration form store mutations', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe(`${types.SET_IS_RESETTING}`, () => {
|
||||
it('sets isResetting', () => {
|
||||
mutations[types.SET_IS_RESETTING](state, true);
|
||||
|
||||
expect(state.isResetting).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe(`${types.REQUEST_RESET_INTEGRATION}`, () => {
|
||||
it('sets isResetting', () => {
|
||||
mutations[types.REQUEST_RESET_INTEGRATION](state);
|
||||
|
||||
expect(state.isResetting).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe(`${types.RECEIVE_RESET_INTEGRATION_ERROR}`, () => {
|
||||
it('sets isResetting', () => {
|
||||
mutations[types.RECEIVE_RESET_INTEGRATION_ERROR](state);
|
||||
|
||||
expect(state.isResetting).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe(`${types.SET_JIRA_ISSUE_TYPES}`, () => {
|
||||
it('sets jiraIssueTypes', () => {
|
||||
const jiraIssueTypes = ['issue', 'epic'];
|
||||
|
|
|
@ -5,8 +5,6 @@ describe('Integration form state factory', () => {
|
|||
expect(createState()).toEqual({
|
||||
defaultState: null,
|
||||
customState: {},
|
||||
isSaving: false,
|
||||
isResetting: false,
|
||||
override: false,
|
||||
isLoadingJiraIssueTypes: false,
|
||||
jiraIssueTypes: [],
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { mount } from '@vue/test-utils';
|
||||
|
||||
import component from '~/packages_and_registries/container_registry/explorer/components/registry_breadcrumb.vue';
|
||||
import component from '~/packages_and_registries/shared/components/registry_breadcrumb.vue';
|
||||
|
||||
describe('Registry Breadcrumb', () => {
|
||||
let wrapper;
|
|
@ -87,7 +87,7 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching do
|
|||
end
|
||||
|
||||
context 'when IP is already banned' do
|
||||
subject { gl_auth.find_for_git_client('username', 'password', project: nil, ip: 'ip') }
|
||||
subject { gl_auth.find_for_git_client('username', Gitlab::Password.test_default, project: nil, ip: 'ip') }
|
||||
|
||||
before do
|
||||
expect_next_instance_of(Gitlab::Auth::IpRateLimiter) do |rate_limiter|
|
||||
|
@ -204,16 +204,16 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching do
|
|||
end
|
||||
|
||||
it 'recognizes master passwords' do
|
||||
user = create(:user, password: 'password')
|
||||
user = create(:user, password: Gitlab::Password.test_default)
|
||||
|
||||
expect(gl_auth.find_for_git_client(user.username, 'password', project: nil, ip: 'ip')).to have_attributes(actor: user, project: nil, type: :gitlab_or_ldap, authentication_abilities: described_class.full_authentication_abilities)
|
||||
expect(gl_auth.find_for_git_client(user.username, Gitlab::Password.test_default, project: nil, ip: 'ip')).to have_attributes(actor: user, project: nil, type: :gitlab_or_ldap, authentication_abilities: described_class.full_authentication_abilities)
|
||||
end
|
||||
|
||||
include_examples 'user login operation with unique ip limit' do
|
||||
let(:user) { create(:user, password: 'password') }
|
||||
let(:user) { create(:user, password: Gitlab::Password.test_default) }
|
||||
|
||||
def operation
|
||||
expect(gl_auth.find_for_git_client(user.username, 'password', project: nil, ip: 'ip')).to have_attributes(actor: user, project: nil, type: :gitlab_or_ldap, authentication_abilities: described_class.full_authentication_abilities)
|
||||
expect(gl_auth.find_for_git_client(user.username, Gitlab::Password.test_default, project: nil, ip: 'ip')).to have_attributes(actor: user, project: nil, type: :gitlab_or_ldap, authentication_abilities: described_class.full_authentication_abilities)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -477,7 +477,7 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching do
|
|||
:user,
|
||||
:blocked,
|
||||
username: 'normal_user',
|
||||
password: 'my-secret'
|
||||
password: Gitlab::Password.test_default
|
||||
)
|
||||
|
||||
expect(gl_auth.find_for_git_client(user.username, user.password, project: nil, ip: 'ip'))
|
||||
|
@ -486,7 +486,7 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching do
|
|||
|
||||
context 'when 2fa is enabled globally' do
|
||||
let_it_be(:user) do
|
||||
create(:user, username: 'normal_user', password: 'my-secret', otp_grace_period_started_at: 1.day.ago)
|
||||
create(:user, username: 'normal_user', password: Gitlab::Password.test_default, otp_grace_period_started_at: 1.day.ago)
|
||||
end
|
||||
|
||||
before do
|
||||
|
@ -510,7 +510,7 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching do
|
|||
|
||||
context 'when 2fa is enabled personally' do
|
||||
let(:user) do
|
||||
create(:user, :two_factor, username: 'normal_user', password: 'my-secret', otp_grace_period_started_at: 1.day.ago)
|
||||
create(:user, :two_factor, username: 'normal_user', password: Gitlab::Password.test_default, otp_grace_period_started_at: 1.day.ago)
|
||||
end
|
||||
|
||||
it 'fails' do
|
||||
|
@ -523,7 +523,7 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching do
|
|||
user = create(
|
||||
:user,
|
||||
username: 'normal_user',
|
||||
password: 'my-secret'
|
||||
password: Gitlab::Password.test_default
|
||||
)
|
||||
|
||||
expect(gl_auth.find_for_git_client(user.username, user.password, project: nil, ip: 'ip'))
|
||||
|
@ -534,7 +534,7 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching do
|
|||
user = create(
|
||||
:user,
|
||||
username: 'oauth2',
|
||||
password: 'my-secret'
|
||||
password: Gitlab::Password.test_default
|
||||
)
|
||||
|
||||
expect(gl_auth.find_for_git_client(user.username, user.password, project: nil, ip: 'ip'))
|
||||
|
@ -609,7 +609,7 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching do
|
|||
|
||||
context 'when deploy token and user have the same username' do
|
||||
let(:username) { 'normal_user' }
|
||||
let(:user) { create(:user, username: username, password: 'my-secret') }
|
||||
let(:user) { create(:user, username: username, password: Gitlab::Password.test_default) }
|
||||
let(:deploy_token) { create(:deploy_token, username: username, read_registry: false, projects: [project]) }
|
||||
|
||||
it 'succeeds for the token' do
|
||||
|
@ -622,7 +622,7 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching do
|
|||
it 'succeeds for the user' do
|
||||
auth_success = { actor: user, project: nil, type: :gitlab_or_ldap, authentication_abilities: described_class.full_authentication_abilities }
|
||||
|
||||
expect(gl_auth.find_for_git_client(username, 'my-secret', project: project, ip: 'ip'))
|
||||
expect(gl_auth.find_for_git_client(username, Gitlab::Password.test_default, project: project, ip: 'ip'))
|
||||
.to have_attributes(auth_success)
|
||||
end
|
||||
end
|
||||
|
@ -816,7 +816,7 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching do
|
|||
end
|
||||
|
||||
let(:username) { 'John' } # username isn't lowercase, test this
|
||||
let(:password) { 'my-secret' }
|
||||
let(:password) { Gitlab::Password.test_default }
|
||||
|
||||
it "finds user by valid login/password" do
|
||||
expect(gl_auth.find_with_user_password(username, password)).to eql user
|
||||
|
@ -941,13 +941,13 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching do
|
|||
it "does not find user by using ldap as fallback to for authentication" do
|
||||
expect(Gitlab::Auth::Ldap::Authentication).to receive(:login).and_return(nil)
|
||||
|
||||
expect(gl_auth.find_with_user_password('ldap_user', 'password')).to be_nil
|
||||
expect(gl_auth.find_with_user_password('ldap_user', Gitlab::Password.test_default)).to be_nil
|
||||
end
|
||||
|
||||
it "find new user by using ldap as fallback to for authentication" do
|
||||
expect(Gitlab::Auth::Ldap::Authentication).to receive(:login).and_return(user)
|
||||
|
||||
expect(gl_auth.find_with_user_password('ldap_user', 'password')).to eq(user)
|
||||
expect(gl_auth.find_with_user_password('ldap_user', Gitlab::Password.test_default)).to eq(user)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -49,7 +49,7 @@ RSpec.describe Emails::Profile do
|
|||
|
||||
describe 'for users that signed up, the email' do
|
||||
let(:example_site_path) { root_path }
|
||||
let(:new_user) { create(:user, email: new_user_address, password: "securePassword") }
|
||||
let(:new_user) { create(:user, email: new_user_address, password: Gitlab::Password.test_default) }
|
||||
|
||||
subject { Notify.new_user_email(new_user.id) }
|
||||
|
||||
|
|
|
@ -6,4 +6,10 @@ RSpec.describe Ci::RunnerNamespace do
|
|||
it_behaves_like 'includes Limitable concern' do
|
||||
subject { build(:ci_runner_namespace, group: create(:group, :nested), runner: create(:ci_runner, :group)) }
|
||||
end
|
||||
|
||||
it_behaves_like 'cleanup by a loose foreign key' do
|
||||
let!(:model) { create(:ci_runner_namespace) }
|
||||
|
||||
let!(:parent) { model.namespace }
|
||||
end
|
||||
end
|
||||
|
|
|
@ -37,7 +37,7 @@ RSpec.describe SystemHook do
|
|||
let(:project) { create(:project, namespace: user.namespace) }
|
||||
let(:group) { create(:group) }
|
||||
let(:params) do
|
||||
{ name: 'John Doe', username: 'jduser', email: 'jg@example.com', password: 'mydummypass' }
|
||||
{ name: 'John Doe', username: 'jduser', email: 'jg@example.com', password: Gitlab::Password.test_default }
|
||||
end
|
||||
|
||||
before do
|
||||
|
|
|
@ -1672,9 +1672,9 @@ RSpec.describe User do
|
|||
|
||||
describe '#generate_password' do
|
||||
it 'does not generate password by default' do
|
||||
user = create(:user, password: 'abcdefghe')
|
||||
user = create(:user, password: Gitlab::Password.test_default)
|
||||
|
||||
expect(user.password).to eq('abcdefghe')
|
||||
expect(user.password).to eq(Gitlab::Password.test_default)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -1027,7 +1027,7 @@ RSpec.describe API::Users do
|
|||
post api('/users', admin),
|
||||
params: {
|
||||
email: 'invalid email',
|
||||
password: 'password',
|
||||
password: Gitlab::Password.test_default,
|
||||
name: 'test'
|
||||
}
|
||||
expect(response).to have_gitlab_http_status(:bad_request)
|
||||
|
@ -1093,7 +1093,7 @@ RSpec.describe API::Users do
|
|||
post api('/users', admin),
|
||||
params: {
|
||||
email: 'test@example.com',
|
||||
password: 'password',
|
||||
password: Gitlab::Password.test_default,
|
||||
username: 'test',
|
||||
name: 'foo'
|
||||
}
|
||||
|
@ -1105,7 +1105,7 @@ RSpec.describe API::Users do
|
|||
params: {
|
||||
name: 'foo',
|
||||
email: 'test@example.com',
|
||||
password: 'password',
|
||||
password: Gitlab::Password.test_default,
|
||||
username: 'foo'
|
||||
}
|
||||
end.to change { User.count }.by(0)
|
||||
|
@ -1119,7 +1119,7 @@ RSpec.describe API::Users do
|
|||
params: {
|
||||
name: 'foo',
|
||||
email: 'foo@example.com',
|
||||
password: 'password',
|
||||
password: Gitlab::Password.test_default,
|
||||
username: 'test'
|
||||
}
|
||||
end.to change { User.count }.by(0)
|
||||
|
@ -1133,7 +1133,7 @@ RSpec.describe API::Users do
|
|||
params: {
|
||||
name: 'foo',
|
||||
email: 'foo@example.com',
|
||||
password: 'password',
|
||||
password: Gitlab::Password.test_default,
|
||||
username: 'TEST'
|
||||
}
|
||||
end.to change { User.count }.by(0)
|
||||
|
@ -1478,8 +1478,8 @@ RSpec.describe API::Users do
|
|||
|
||||
context "with existing user" do
|
||||
before do
|
||||
post api("/users", admin), params: { email: 'test@example.com', password: 'password', username: 'test', name: 'test' }
|
||||
post api("/users", admin), params: { email: 'foo@bar.com', password: 'password', username: 'john', name: 'john' }
|
||||
post api("/users", admin), params: { email: 'test@example.com', password: Gitlab::Password.test_default, username: 'test', name: 'test' }
|
||||
post api("/users", admin), params: { email: 'foo@bar.com', password: Gitlab::Password.test_default, username: 'john', name: 'john' }
|
||||
@user = User.all.last
|
||||
end
|
||||
|
||||
|
|
|
@ -319,7 +319,7 @@ RSpec.describe 'Git HTTP requests' do
|
|||
context 'when user is using credentials with special characters' do
|
||||
context 'with password with special characters' do
|
||||
before do
|
||||
user.update!(password: 'RKszEwéC5kFnû∆f243fycGu§Gh9ftDj!U')
|
||||
user.update!(password: Gitlab::Password.test_default)
|
||||
end
|
||||
|
||||
it 'allows clones' do
|
||||
|
@ -1670,7 +1670,7 @@ RSpec.describe 'Git HTTP requests' do
|
|||
context 'when user is using credentials with special characters' do
|
||||
context 'with password with special characters' do
|
||||
before do
|
||||
user.update!(password: 'RKszEwéC5kFnû∆f243fycGu§Gh9ftDj!U')
|
||||
user.update!(password: Gitlab::Password.test_default)
|
||||
end
|
||||
|
||||
it 'allows clones' do
|
||||
|
|
|
@ -43,24 +43,18 @@ RSpec.describe RuboCop::Cop::Migration::ScheduleAsync do
|
|||
end
|
||||
|
||||
context 'BackgroundMigrationWorker.perform_async' do
|
||||
it 'adds an offense when calling `BackgroundMigrationWorker.peform_async` and corrects', :aggregate_failures do
|
||||
it 'adds an offense when calling `BackgroundMigrationWorker.peform_async`' do
|
||||
expect_offense(<<~RUBY)
|
||||
def up
|
||||
BackgroundMigrationWorker.perform_async(ClazzName, "Bar", "Baz")
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Don't call [...]
|
||||
end
|
||||
RUBY
|
||||
|
||||
expect_correction(<<~RUBY)
|
||||
def up
|
||||
migrate_async(ClazzName, "Bar", "Baz")
|
||||
end
|
||||
RUBY
|
||||
end
|
||||
end
|
||||
|
||||
context 'BackgroundMigrationWorker.perform_in' do
|
||||
it 'adds an offense and corrects', :aggregate_failures do
|
||||
it 'adds an offense' do
|
||||
expect_offense(<<~RUBY)
|
||||
def up
|
||||
BackgroundMigrationWorker
|
||||
|
@ -68,17 +62,11 @@ RSpec.describe RuboCop::Cop::Migration::ScheduleAsync do
|
|||
.perform_in(delay, ClazzName, "Bar", "Baz")
|
||||
end
|
||||
RUBY
|
||||
|
||||
expect_correction(<<~RUBY)
|
||||
def up
|
||||
migrate_in(delay, ClazzName, "Bar", "Baz")
|
||||
end
|
||||
RUBY
|
||||
end
|
||||
end
|
||||
|
||||
context 'BackgroundMigrationWorker.bulk_perform_async' do
|
||||
it 'adds an offense and corrects', :aggregate_failures do
|
||||
it 'adds an offense' do
|
||||
expect_offense(<<~RUBY)
|
||||
def up
|
||||
BackgroundMigrationWorker
|
||||
|
@ -86,17 +74,11 @@ RSpec.describe RuboCop::Cop::Migration::ScheduleAsync do
|
|||
.bulk_perform_async(jobs)
|
||||
end
|
||||
RUBY
|
||||
|
||||
expect_correction(<<~RUBY)
|
||||
def up
|
||||
bulk_migrate_async(jobs)
|
||||
end
|
||||
RUBY
|
||||
end
|
||||
end
|
||||
|
||||
context 'BackgroundMigrationWorker.bulk_perform_in' do
|
||||
it 'adds an offense and corrects', :aggregate_failures do
|
||||
it 'adds an offense' do
|
||||
expect_offense(<<~RUBY)
|
||||
def up
|
||||
BackgroundMigrationWorker
|
||||
|
@ -104,12 +86,6 @@ RSpec.describe RuboCop::Cop::Migration::ScheduleAsync do
|
|||
.bulk_perform_in(5.minutes, jobs)
|
||||
end
|
||||
RUBY
|
||||
|
||||
expect_correction(<<~RUBY)
|
||||
def up
|
||||
bulk_migrate_in(5.minutes, jobs)
|
||||
end
|
||||
RUBY
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -62,6 +62,10 @@ RSpec.describe GroupChildEntity do
|
|||
expect(json[:edit_path]).to eq(edit_project_path(object))
|
||||
end
|
||||
|
||||
it 'includes the last activity at' do
|
||||
expect(json[:last_activity_at]).to be_present
|
||||
end
|
||||
|
||||
it_behaves_like 'group child json'
|
||||
end
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ RSpec.describe Users::CreateService do
|
|||
|
||||
context 'when required parameters are provided' do
|
||||
let(:params) do
|
||||
{ name: 'John Doe', username: 'jduser', email: email, password: 'mydummypass' }
|
||||
{ name: 'John Doe', username: 'jduser', email: email, password: Gitlab::Password.test_default }
|
||||
end
|
||||
|
||||
it 'returns a persisted user' do
|
||||
|
@ -82,13 +82,13 @@ RSpec.describe Users::CreateService do
|
|||
|
||||
context 'when force_random_password parameter is true' do
|
||||
let(:params) do
|
||||
{ name: 'John Doe', username: 'jduser', email: 'jd@example.com', password: 'mydummypass', force_random_password: true }
|
||||
{ name: 'John Doe', username: 'jduser', email: 'jd@example.com', password: Gitlab::Password.test_default, force_random_password: true }
|
||||
end
|
||||
|
||||
it 'generates random password' do
|
||||
user = service.execute
|
||||
|
||||
expect(user.password).not_to eq 'mydummypass'
|
||||
expect(user.password).not_to eq Gitlab::Password.test_default
|
||||
expect(user.password).to be_present
|
||||
end
|
||||
end
|
||||
|
@ -99,7 +99,7 @@ RSpec.describe Users::CreateService do
|
|||
name: 'John Doe',
|
||||
username: 'jduser',
|
||||
email: 'jd@example.com',
|
||||
password: 'mydummypass',
|
||||
password: Gitlab::Password.test_default,
|
||||
password_automatically_set: true
|
||||
}
|
||||
end
|
||||
|
@ -121,7 +121,7 @@ RSpec.describe Users::CreateService do
|
|||
|
||||
context 'when skip_confirmation parameter is true' do
|
||||
let(:params) do
|
||||
{ name: 'John Doe', username: 'jduser', email: 'jd@example.com', password: 'mydummypass', skip_confirmation: true }
|
||||
{ name: 'John Doe', username: 'jduser', email: 'jd@example.com', password: Gitlab::Password.test_default, skip_confirmation: true }
|
||||
end
|
||||
|
||||
it 'confirms the user' do
|
||||
|
@ -131,7 +131,7 @@ RSpec.describe Users::CreateService do
|
|||
|
||||
context 'when reset_password parameter is true' do
|
||||
let(:params) do
|
||||
{ name: 'John Doe', username: 'jduser', email: 'jd@example.com', password: 'mydummypass', reset_password: true }
|
||||
{ name: 'John Doe', username: 'jduser', email: 'jd@example.com', password: Gitlab::Password.test_default, reset_password: true }
|
||||
end
|
||||
|
||||
it 'resets password even if a password parameter is given' do
|
||||
|
@ -152,7 +152,7 @@ RSpec.describe Users::CreateService do
|
|||
|
||||
context 'with nil user' do
|
||||
let(:params) do
|
||||
{ name: 'John Doe', username: 'jduser', email: 'jd@example.com', password: 'mydummypass', skip_confirmation: true }
|
||||
{ name: 'John Doe', username: 'jduser', email: 'jd@example.com', password: Gitlab::Password.test_default, skip_confirmation: true }
|
||||
end
|
||||
|
||||
let(:service) { described_class.new(nil, params) }
|
||||
|
|
|
@ -95,7 +95,7 @@ module LoginHelpers
|
|||
visit new_user_session_path
|
||||
|
||||
fill_in "user_login", with: user.email
|
||||
fill_in "user_password", with: "12345678"
|
||||
fill_in "user_password", with: Gitlab::Password.test_default
|
||||
check 'user_remember_me' if remember
|
||||
|
||||
click_button "Sign in"
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
require 'rake_helper'
|
||||
|
||||
RSpec.describe 'gitlab:password rake tasks', :silence_stdout do
|
||||
let_it_be(:user_1) { create(:user, username: 'foobar', password: 'initial_password') }
|
||||
let_it_be(:user_1) { create(:user, username: 'foobar', password: Gitlab::Password.test_default) }
|
||||
|
||||
def stub_username(username)
|
||||
allow(Gitlab::TaskHelpers).to receive(:prompt).with('Enter username: ').and_return(username)
|
||||
|
@ -19,14 +19,14 @@ RSpec.describe 'gitlab:password rake tasks', :silence_stdout do
|
|||
Rake.application.rake_require 'tasks/gitlab/password'
|
||||
|
||||
stub_username('foobar')
|
||||
stub_password('secretpassword')
|
||||
stub_password(Gitlab::Password.test_default)
|
||||
end
|
||||
|
||||
describe ':reset' do
|
||||
context 'when all inputs are correct' do
|
||||
it 'updates the password properly' do
|
||||
run_rake_task('gitlab:password:reset', user_1.username)
|
||||
expect(user_1.reload.valid_password?('secretpassword')).to eq(true)
|
||||
expect(user_1.reload.valid_password?(Gitlab::Password.test_default)).to eq(true)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -55,7 +55,7 @@ RSpec.describe 'gitlab:password rake tasks', :silence_stdout do
|
|||
|
||||
context 'when passwords do not match' do
|
||||
before do
|
||||
stub_password('randompassword', 'differentpassword')
|
||||
stub_password(Gitlab::Password.test_default, "different" + Gitlab::Password.test_default)
|
||||
end
|
||||
|
||||
it 'aborts with an error' do
|
||||
|
|
|
@ -10,16 +10,34 @@ RSpec.describe Metrics::Dashboard::SyncDashboardsWorker do
|
|||
let(:dashboard_path) { '.gitlab/dashboards/test.yml' }
|
||||
|
||||
describe ".perform" do
|
||||
it 'imports metrics' do
|
||||
expect { worker.perform(project.id) }.to change(PrometheusMetric, :count).by(3)
|
||||
end
|
||||
|
||||
it 'is idempotent' do
|
||||
2.times do
|
||||
worker.perform(project.id)
|
||||
context 'with valid dashboard hash' do
|
||||
it 'imports metrics' do
|
||||
expect { worker.perform(project.id) }.to change(PrometheusMetric, :count).by(3)
|
||||
end
|
||||
|
||||
expect(PrometheusMetric.count).to eq(3)
|
||||
it 'is idempotent' do
|
||||
2.times do
|
||||
worker.perform(project.id)
|
||||
end
|
||||
|
||||
expect(PrometheusMetric.count).to eq(3)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with invalid dashboard hash' do
|
||||
before do
|
||||
allow_next_instance_of(Gitlab::Metrics::Dashboard::Importer) do |instance|
|
||||
allow(instance).to receive(:dashboard_hash).and_return({})
|
||||
end
|
||||
end
|
||||
|
||||
it 'does not import metrics' do
|
||||
expect { worker.perform(project.id) }.not_to change(PrometheusMetric, :count)
|
||||
end
|
||||
|
||||
it 'does not raise an error' do
|
||||
expect { worker.perform(project.id) }.not_to raise_error
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue