Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
60eaf3d906
commit
054378fd4a
|
@ -10,6 +10,21 @@ const KEY_WEB_IDE = 'webide';
|
|||
const KEY_GITPOD = 'gitpod';
|
||||
const KEY_PIPELINE_EDITOR = 'pipeline_editor';
|
||||
|
||||
export const i18n = {
|
||||
modal: {
|
||||
title: __('Enable Gitpod?'),
|
||||
content: s__(
|
||||
'Gitpod|To use Gitpod you must first enable the feature in the integrations section of your %{linkStart}user preferences%{linkEnd}.',
|
||||
),
|
||||
actionCancelText: __('Cancel'),
|
||||
actionPrimaryText: __('Enable Gitpod'),
|
||||
},
|
||||
webIdeText: s__('WebIDE|Quickly and easily edit multiple files in your project.'),
|
||||
webIdeTooltip: s__(
|
||||
'WebIDE|Quickly and easily edit multiple files in your project. Press . to open',
|
||||
),
|
||||
};
|
||||
|
||||
export default {
|
||||
components: {
|
||||
ActionsButton,
|
||||
|
@ -19,16 +34,7 @@ export default {
|
|||
GlLink,
|
||||
ConfirmForkModal,
|
||||
},
|
||||
i18n: {
|
||||
modal: {
|
||||
title: __('Enable Gitpod?'),
|
||||
content: s__(
|
||||
'Gitpod|To use Gitpod you must first enable the feature in the integrations section of your %{linkStart}user preferences%{linkEnd}.',
|
||||
),
|
||||
actionCancelText: __('Cancel'),
|
||||
actionPrimaryText: __('Enable Gitpod'),
|
||||
},
|
||||
},
|
||||
i18n,
|
||||
props: {
|
||||
isFork: {
|
||||
type: Boolean,
|
||||
|
@ -207,8 +213,8 @@ export default {
|
|||
return {
|
||||
key: KEY_WEB_IDE,
|
||||
text: this.webIdeActionText,
|
||||
secondaryText: __('Quickly and easily edit multiple files in your project.'),
|
||||
tooltip: '',
|
||||
secondaryText: this.$options.i18n.webIdeText,
|
||||
tooltip: this.$options.i18n.webIdeTooltip,
|
||||
attrs: {
|
||||
'data-qa-selector': 'web_ide_button',
|
||||
'data-track-action': 'click_consolidated_edit_ide',
|
||||
|
|
|
@ -16,4 +16,14 @@ class OauthAccessToken < Doorkeeper::AccessToken
|
|||
super
|
||||
end
|
||||
end
|
||||
|
||||
# this method overrides a shortcoming upstream, more context:
|
||||
# https://gitlab.com/gitlab-org/gitlab/-/issues/367888
|
||||
def self.find_by_fallback_token(attr, plain_secret)
|
||||
return unless fallback_secret_strategy && fallback_secret_strategy == Doorkeeper::SecretStoring::Plain
|
||||
# token is hashed, don't allow plaintext comparison
|
||||
return if plain_secret.starts_with?("$")
|
||||
|
||||
super
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
name: hash_oauth_tokens
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91501
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/367570
|
||||
milestone: '15.3'
|
||||
type: development
|
||||
group: group::authentication and authorization
|
||||
default_enabled: false
|
|
@ -90,6 +90,8 @@ Doorkeeper.configure do
|
|||
# Check out the wiki for more information on customization
|
||||
access_token_methods :from_access_token_param, :from_bearer_authorization, :from_bearer_param
|
||||
|
||||
hash_token_secrets using: '::Gitlab::DoorkeeperSecretStoring::Pbkdf2Sha512', fallback: :plain
|
||||
|
||||
# Specify what grant flows are enabled in array of Strings. The valid
|
||||
# strings and the flows they enable are:
|
||||
#
|
||||
|
|
|
@ -81,6 +81,36 @@ This requires you to either:
|
|||
|
||||
### Documentation link tests
|
||||
|
||||
Merge requests containing changes to Markdown (`.md`) files run a `docs-lint links`
|
||||
job, which runs two types of link checks. In both cases, links with destinations
|
||||
that begin with `http` or `https` are considered external links, and skipped:
|
||||
|
||||
- `bundle exec nanoc check internal_links`: Tests links to internal pages.
|
||||
- `bundle exec nanoc check internal_anchors`: Tests links to subheadings (anchors) on internal pages.
|
||||
|
||||
Failures from these tests are displayed at the end of the test results in the **Issues found!** area.
|
||||
For example, failures in the `internal_anchors` test follow this format:
|
||||
|
||||
```plaintext
|
||||
[ ERROR ] internal_anchors - Broken anchor detected!
|
||||
- source file `/tmp/gitlab-docs/public/ee/user/application_security/api_fuzzing/index.html`
|
||||
- destination `/tmp/gitlab-docs/public/ee/development/code_review.html`
|
||||
- link `../../../development/code_review.html#review-response-slo`
|
||||
- anchor `#review-response-slo`
|
||||
```
|
||||
|
||||
- **Source file**: The full path to the file containing the error. To find the
|
||||
file in the `gitlab` repository, replace `/tmp/gitlab-docs/public/ee` with `doc`, and `.html` with `.md`.
|
||||
- **Destination**: The full path to the file not found by the test. To find the
|
||||
file in the `gitlab` repository, replace `/tmp/gitlab-docs/public/ee` with `doc`, and `.html` with `.md`.
|
||||
- **Link**: The actual link the script attempted to find.
|
||||
- **Anchor**: If present, the subheading (anchor) the script attempted to find.
|
||||
|
||||
Check for multiple instances of the same broken link on each page reporting an error.
|
||||
Even if a specific broken link appears multiple times on a page, the test reports it only once.
|
||||
|
||||
#### Run document link tests locally
|
||||
|
||||
To execute documentation link tests locally:
|
||||
|
||||
1. Navigate to the [`gitlab-docs`](https://gitlab.com/gitlab-org/gitlab-docs) directory.
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Gitlab
|
||||
module DoorkeeperSecretStoring
|
||||
class Pbkdf2Sha512 < ::Doorkeeper::SecretStoring::Base
|
||||
STRETCHES = 20_000
|
||||
# An empty salt is used because we need to look tokens up solely by
|
||||
# their hashed value. Additionally, tokens are always cryptographically
|
||||
# pseudo-random and unique, therefore salting provides no
|
||||
# additional security.
|
||||
SALT = ''
|
||||
|
||||
def self.transform_secret(plain_secret)
|
||||
return plain_secret unless Feature.enabled?(:hash_oauth_tokens)
|
||||
|
||||
Devise::Pbkdf2Encryptable::Encryptors::Pbkdf2Sha512.digest(plain_secret, STRETCHES, SALT)
|
||||
end
|
||||
|
||||
##
|
||||
# Determines whether this strategy supports restoring
|
||||
# secrets from the database. This allows detecting users
|
||||
# trying to use a non-restorable strategy with +reuse_access_tokens+.
|
||||
def self.allows_restoring_secrets?
|
||||
false
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -32068,9 +32068,6 @@ msgstr ""
|
|||
msgid "Quick range"
|
||||
msgstr ""
|
||||
|
||||
msgid "Quickly and easily edit multiple files in your project."
|
||||
msgstr ""
|
||||
|
||||
msgid "Quota of CI/CD minutes"
|
||||
msgstr ""
|
||||
|
||||
|
@ -43720,6 +43717,12 @@ msgstr ""
|
|||
msgid "WebIDE|Merge request"
|
||||
msgstr ""
|
||||
|
||||
msgid "WebIDE|Quickly and easily edit multiple files in your project."
|
||||
msgstr ""
|
||||
|
||||
msgid "WebIDE|Quickly and easily edit multiple files in your project. Press . to open"
|
||||
msgstr ""
|
||||
|
||||
msgid "WebIDE|This project does not accept unsigned commits."
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -71,7 +71,7 @@ describe('Blob Header Default Actions', () => {
|
|||
});
|
||||
buttons = wrapper.findAllComponents(GlButton);
|
||||
|
||||
expect(buttons.at(0).attributes('disabled')).toBeTruthy();
|
||||
expect(buttons.at(0).attributes('disabled')).toBe('true');
|
||||
});
|
||||
|
||||
it('does not render the copy button if a rendering error is set', () => {
|
||||
|
|
|
@ -69,7 +69,7 @@ describe('Sketch viewer', () => {
|
|||
const img = document.querySelector('#js-sketch-viewer img');
|
||||
|
||||
expect(img).not.toBeNull();
|
||||
expect(img.classList.contains('img-fluid')).toBeTruthy();
|
||||
expect(img.classList.contains('img-fluid')).toBe(true);
|
||||
});
|
||||
|
||||
it('renders link to image', () => {
|
||||
|
|
|
@ -6,8 +6,8 @@ import BatchDeleteButton from '~/design_management/components/delete_button.vue'
|
|||
describe('Batch delete button component', () => {
|
||||
let wrapper;
|
||||
|
||||
const findButton = () => wrapper.find(GlButton);
|
||||
const findModal = () => wrapper.find(GlModal);
|
||||
const findButton = () => wrapper.findComponent(GlButton);
|
||||
const findModal = () => wrapper.findComponent(GlModal);
|
||||
|
||||
function createComponent({ isDeleting = false } = {}, { slots = {} } = {}) {
|
||||
wrapper = shallowMount(BatchDeleteButton, {
|
||||
|
|
|
@ -26,13 +26,13 @@ describe('Design discussions component', () => {
|
|||
const originalGon = window.gon;
|
||||
let wrapper;
|
||||
|
||||
const findDesignNotes = () => wrapper.findAll(DesignNote);
|
||||
const findReplyPlaceholder = () => wrapper.find(ReplyPlaceholder);
|
||||
const findReplyForm = () => wrapper.find(DesignReplyForm);
|
||||
const findRepliesWidget = () => wrapper.find(ToggleRepliesWidget);
|
||||
const findDesignNotes = () => wrapper.findAllComponents(DesignNote);
|
||||
const findReplyPlaceholder = () => wrapper.findComponent(ReplyPlaceholder);
|
||||
const findReplyForm = () => wrapper.findComponent(DesignReplyForm);
|
||||
const findRepliesWidget = () => wrapper.findComponent(ToggleRepliesWidget);
|
||||
const findResolveButton = () => wrapper.find('[data-testid="resolve-button"]');
|
||||
const findResolvedMessage = () => wrapper.find('[data-testid="resolved-message"]');
|
||||
const findResolveLoadingIcon = () => wrapper.find(GlLoadingIcon);
|
||||
const findResolveLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
|
||||
const findResolveCheckbox = () => wrapper.find('[data-testid="resolve-checkbox"]');
|
||||
const findApolloMutation = () => wrapper.findComponent(ApolloMutation);
|
||||
|
||||
|
@ -307,7 +307,7 @@ describe('Design discussions component', () => {
|
|||
|
||||
expect(
|
||||
wrapper
|
||||
.findAll(DesignNote)
|
||||
.findAllComponents(DesignNote)
|
||||
.wrappers.every((designNote) => designNote.classes('gl-bg-blue-50')),
|
||||
).toBe(true);
|
||||
},
|
||||
|
|
|
@ -100,7 +100,7 @@ describe('Design note component', () => {
|
|||
note,
|
||||
});
|
||||
|
||||
expect(wrapper.find(TimeAgoTooltip).exists()).toBe(true);
|
||||
expect(wrapper.findComponent(TimeAgoTooltip).exists()).toBe(true);
|
||||
});
|
||||
|
||||
it('should not render edit icon when user does not have a permission', () => {
|
||||
|
|
|
@ -15,9 +15,9 @@ describe('Design reply form component', () => {
|
|||
let wrapper;
|
||||
|
||||
const findTextarea = () => wrapper.find('textarea');
|
||||
const findSubmitButton = () => wrapper.find({ ref: 'submitButton' });
|
||||
const findCancelButton = () => wrapper.find({ ref: 'cancelButton' });
|
||||
const findModal = () => wrapper.find({ ref: 'cancelCommentModal' });
|
||||
const findSubmitButton = () => wrapper.findComponent({ ref: 'submitButton' });
|
||||
const findCancelButton = () => wrapper.findComponent({ ref: 'cancelButton' });
|
||||
const findModal = () => wrapper.findComponent({ ref: 'cancelCommentModal' });
|
||||
|
||||
function createComponent(props = {}, mountOptions = {}) {
|
||||
wrapper = mount(DesignReplyForm, {
|
||||
|
|
|
@ -8,10 +8,10 @@ describe('Toggle replies widget component', () => {
|
|||
let wrapper;
|
||||
|
||||
const findToggleWrapper = () => wrapper.find('[data-testid="toggle-comments-wrapper"]');
|
||||
const findIcon = () => wrapper.find(GlIcon);
|
||||
const findButton = () => wrapper.find(GlButton);
|
||||
const findAuthorLink = () => wrapper.find(GlLink);
|
||||
const findTimeAgo = () => wrapper.find(TimeAgoTooltip);
|
||||
const findIcon = () => wrapper.findComponent(GlIcon);
|
||||
const findButton = () => wrapper.findComponent(GlButton);
|
||||
const findAuthorLink = () => wrapper.findComponent(GlLink);
|
||||
const findTimeAgo = () => wrapper.findComponent(TimeAgoTooltip);
|
||||
|
||||
function createComponent(props = {}) {
|
||||
wrapper = shallowMount(ToggleRepliesWidget, {
|
||||
|
|
|
@ -6,7 +6,7 @@ import DesignScaler from '~/design_management/components/design_scaler.vue';
|
|||
describe('Design management design scaler component', () => {
|
||||
let wrapper;
|
||||
|
||||
const getButtons = () => wrapper.findAll(GlButton);
|
||||
const getButtons = () => wrapper.findAllComponents(GlButton);
|
||||
const getDecreaseScaleButton = () => getButtons().at(0);
|
||||
const getResetScaleButton = () => getButtons().at(1);
|
||||
const getIncreaseScaleButton = () => getButtons().at(2);
|
||||
|
|
|
@ -32,12 +32,12 @@ describe('Design management design sidebar component', () => {
|
|||
const originalGon = window.gon;
|
||||
let wrapper;
|
||||
|
||||
const findDiscussions = () => wrapper.findAll(DesignDiscussion);
|
||||
const findDiscussions = () => wrapper.findAllComponents(DesignDiscussion);
|
||||
const findFirstDiscussion = () => findDiscussions().at(0);
|
||||
const findUnresolvedDiscussions = () => wrapper.findAll('[data-testid="unresolved-discussion"]');
|
||||
const findResolvedDiscussions = () => wrapper.findAll('[data-testid="resolved-discussion"]');
|
||||
const findParticipants = () => wrapper.find(Participants);
|
||||
const findResolvedCommentsToggle = () => wrapper.find(GlAccordionItem);
|
||||
const findParticipants = () => wrapper.findComponent(Participants);
|
||||
const findResolvedCommentsToggle = () => wrapper.findComponent(GlAccordionItem);
|
||||
const findNewDiscussionDisclaimer = () =>
|
||||
wrapper.find('[data-testid="new-discussion-disclaimer"]');
|
||||
|
||||
|
@ -87,7 +87,7 @@ describe('Design management design sidebar component', () => {
|
|||
it('renders To-Do button', () => {
|
||||
createComponent();
|
||||
|
||||
expect(wrapper.find(DesignTodoButton).exists()).toBe(true);
|
||||
expect(wrapper.findComponent(DesignTodoButton).exists()).toBe(true);
|
||||
});
|
||||
|
||||
describe('when has no discussions', () => {
|
||||
|
|
|
@ -57,7 +57,7 @@ describe('Design management design todo button', () => {
|
|||
});
|
||||
|
||||
it('renders TodoButton component', () => {
|
||||
expect(wrapper.find(TodoButton).exists()).toBe(true);
|
||||
expect(wrapper.findComponent(TodoButton).exists()).toBe(true);
|
||||
});
|
||||
|
||||
describe('when design has a pending todo', () => {
|
||||
|
|
|
@ -71,7 +71,7 @@ describe('Design management large image component', () => {
|
|||
image.trigger('error');
|
||||
await nextTick();
|
||||
expect(image.isVisible()).toBe(false);
|
||||
expect(wrapper.find(GlIcon).element).toMatchSnapshot();
|
||||
expect(wrapper.findComponent(GlIcon).element).toMatchSnapshot();
|
||||
});
|
||||
|
||||
describe('zoom', () => {
|
||||
|
|
|
@ -23,8 +23,8 @@ describe('Design management list item component', () => {
|
|||
|
||||
const findDesignEvent = () => wrapper.findByTestId('design-event');
|
||||
const findImgFilename = (id = imgId) => wrapper.findByTestId(`design-img-filename-${id}`);
|
||||
const findEventIcon = () => findDesignEvent().find(GlIcon);
|
||||
const findLoadingIcon = () => wrapper.find(GlLoadingIcon);
|
||||
const findEventIcon = () => findDesignEvent().findComponent(GlIcon);
|
||||
const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
|
||||
|
||||
function createComponent({
|
||||
notesCount = 0,
|
||||
|
@ -74,7 +74,7 @@ describe('Design management list item component', () => {
|
|||
beforeEach(async () => {
|
||||
createComponent();
|
||||
image = wrapper.find('img');
|
||||
glIntersectionObserver = wrapper.find(GlIntersectionObserver);
|
||||
glIntersectionObserver = wrapper.findComponent(GlIntersectionObserver);
|
||||
|
||||
glIntersectionObserver.vm.$emit('appear');
|
||||
await nextTick();
|
||||
|
@ -86,7 +86,7 @@ describe('Design management list item component', () => {
|
|||
|
||||
describe('before image is loaded', () => {
|
||||
it('renders loading spinner', () => {
|
||||
expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
|
||||
expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -105,7 +105,7 @@ describe('Design management list item component', () => {
|
|||
image.trigger('error');
|
||||
await nextTick();
|
||||
expect(image.isVisible()).toBe(false);
|
||||
expect(wrapper.find(GlIcon).element).toMatchSnapshot();
|
||||
expect(wrapper.findComponent(GlIcon).element).toMatchSnapshot();
|
||||
});
|
||||
|
||||
describe('when imageV432x230 and image provided', () => {
|
||||
|
|
|
@ -85,35 +85,35 @@ describe('Design management toolbar component', () => {
|
|||
createComponent();
|
||||
|
||||
await nextTick();
|
||||
expect(wrapper.find(DeleteButton).exists()).toBe(true);
|
||||
expect(wrapper.findComponent(DeleteButton).exists()).toBe(true);
|
||||
});
|
||||
|
||||
it('does not render delete button on non-latest version', async () => {
|
||||
createComponent(false, true, { isLatestVersion: false });
|
||||
|
||||
await nextTick();
|
||||
expect(wrapper.find(DeleteButton).exists()).toBe(false);
|
||||
expect(wrapper.findComponent(DeleteButton).exists()).toBe(false);
|
||||
});
|
||||
|
||||
it('does not render delete button when user is not logged in', async () => {
|
||||
createComponent(false, false);
|
||||
|
||||
await nextTick();
|
||||
expect(wrapper.find(DeleteButton).exists()).toBe(false);
|
||||
expect(wrapper.findComponent(DeleteButton).exists()).toBe(false);
|
||||
});
|
||||
|
||||
it('emits `delete` event on deleteButton `delete-selected-designs` event', async () => {
|
||||
createComponent();
|
||||
|
||||
await nextTick();
|
||||
wrapper.find(DeleteButton).vm.$emit('delete-selected-designs');
|
||||
wrapper.findComponent(DeleteButton).vm.$emit('delete-selected-designs');
|
||||
expect(wrapper.emitted().delete).toBeTruthy();
|
||||
});
|
||||
|
||||
it('renders download button with correct link', () => {
|
||||
createComponent();
|
||||
|
||||
expect(wrapper.find(GlButton).attributes('href')).toBe(
|
||||
expect(wrapper.findComponent(GlButton).attributes('href')).toBe(
|
||||
'/-/designs/306/7f747adcd4693afadbe968d7ba7d983349b9012d',
|
||||
);
|
||||
});
|
||||
|
|
|
@ -34,7 +34,7 @@ describe('Design management upload button component', () => {
|
|||
it('Button `loading` prop is `true`', () => {
|
||||
createComponent({ isSaving: true });
|
||||
|
||||
const button = wrapper.find(GlButton);
|
||||
const button = wrapper.findComponent(GlButton);
|
||||
expect(button.exists()).toBe(true);
|
||||
expect(button.props('loading')).toBe(true);
|
||||
});
|
||||
|
|
|
@ -46,7 +46,7 @@ describe('Design management design version dropdown component', () => {
|
|||
wrapper.destroy();
|
||||
});
|
||||
|
||||
const findVersionLink = (index) => wrapper.findAll(GlDropdownItem).at(index);
|
||||
const findVersionLink = (index) => wrapper.findAllComponents(GlDropdownItem).at(index);
|
||||
|
||||
it('renders design version dropdown button', async () => {
|
||||
createComponent();
|
||||
|
@ -76,35 +76,35 @@ describe('Design management design version dropdown component', () => {
|
|||
createComponent();
|
||||
|
||||
await nextTick();
|
||||
expect(wrapper.find(GlDropdown).attributes('text')).toBe('Showing latest version');
|
||||
expect(wrapper.findComponent(GlDropdown).attributes('text')).toBe('Showing latest version');
|
||||
});
|
||||
|
||||
it('displays latest version text when only 1 version is present', async () => {
|
||||
createComponent({ maxVersions: 1 });
|
||||
|
||||
await nextTick();
|
||||
expect(wrapper.find(GlDropdown).attributes('text')).toBe('Showing latest version');
|
||||
expect(wrapper.findComponent(GlDropdown).attributes('text')).toBe('Showing latest version');
|
||||
});
|
||||
|
||||
it('displays version text when the current version is not the latest', async () => {
|
||||
createComponent({ $route: designRouteFactory(PREVIOUS_VERSION_ID) });
|
||||
|
||||
await nextTick();
|
||||
expect(wrapper.find(GlDropdown).attributes('text')).toBe(`Showing version #1`);
|
||||
expect(wrapper.findComponent(GlDropdown).attributes('text')).toBe(`Showing version #1`);
|
||||
});
|
||||
|
||||
it('displays latest version text when the current version is the latest', async () => {
|
||||
createComponent({ $route: designRouteFactory(LATEST_VERSION_ID) });
|
||||
|
||||
await nextTick();
|
||||
expect(wrapper.find(GlDropdown).attributes('text')).toBe('Showing latest version');
|
||||
expect(wrapper.findComponent(GlDropdown).attributes('text')).toBe('Showing latest version');
|
||||
});
|
||||
|
||||
it('should have the same length as apollo query', async () => {
|
||||
createComponent();
|
||||
|
||||
await nextTick();
|
||||
expect(wrapper.findAll(GlDropdownItem)).toHaveLength(wrapper.vm.allVersions.length);
|
||||
expect(wrapper.findAllComponents(GlDropdownItem)).toHaveLength(wrapper.vm.allVersions.length);
|
||||
});
|
||||
|
||||
it('should render TimeAgo', async () => {
|
||||
|
|
|
@ -85,9 +85,9 @@ describe('Design management design index page', () => {
|
|||
let wrapper;
|
||||
let router;
|
||||
|
||||
const findDiscussionForm = () => wrapper.find(DesignReplyForm);
|
||||
const findSidebar = () => wrapper.find(DesignSidebar);
|
||||
const findDesignPresentation = () => wrapper.find(DesignPresentation);
|
||||
const findDiscussionForm = () => wrapper.findComponent(DesignReplyForm);
|
||||
const findSidebar = () => wrapper.findComponent(DesignSidebar);
|
||||
const findDesignPresentation = () => wrapper.findComponent(DesignPresentation);
|
||||
|
||||
function createComponent(
|
||||
{ loading = false } = {},
|
||||
|
@ -181,15 +181,15 @@ describe('Design management design index page', () => {
|
|||
it('sets loading state', () => {
|
||||
createComponent({ loading: true });
|
||||
|
||||
expect(wrapper.find(DesignPresentation).props('isLoading')).toBe(true);
|
||||
expect(wrapper.find(DesignSidebar).props('isLoading')).toBe(true);
|
||||
expect(wrapper.findComponent(DesignPresentation).props('isLoading')).toBe(true);
|
||||
expect(wrapper.findComponent(DesignSidebar).props('isLoading')).toBe(true);
|
||||
});
|
||||
|
||||
it('renders design index', () => {
|
||||
createComponent({ loading: false }, { data: { design } });
|
||||
|
||||
expect(wrapper.element).toMatchSnapshot();
|
||||
expect(wrapper.find(GlAlert).exists()).toBe(false);
|
||||
expect(wrapper.findComponent(GlAlert).exists()).toBe(false);
|
||||
});
|
||||
|
||||
it('passes correct props to sidebar component', () => {
|
||||
|
|
|
@ -111,8 +111,8 @@ describe('Design management index page', () => {
|
|||
const findDropzoneWrapper = () => wrapper.findByTestId('design-dropzone-wrapper');
|
||||
const findFirstDropzoneWithDesign = () => wrapper.findAllComponents(DesignDropzone).at(1);
|
||||
const findDesignsWrapper = () => wrapper.findByTestId('designs-root');
|
||||
const findDesigns = () => wrapper.findAll(Design);
|
||||
const draggableAttributes = () => wrapper.find(VueDraggable).vm.$attrs;
|
||||
const findDesigns = () => wrapper.findAllComponents(Design);
|
||||
const draggableAttributes = () => wrapper.findComponent(VueDraggable).vm.$attrs;
|
||||
const findDesignUploadButton = () => wrapper.findByTestId('design-upload-button');
|
||||
const findDesignToolbarWrapper = () => wrapper.findByTestId('design-toolbar-wrapper');
|
||||
const findDesignUpdateAlert = () => wrapper.findByTestId('design-update-alert');
|
||||
|
@ -120,8 +120,8 @@ describe('Design management index page', () => {
|
|||
async function moveDesigns(localWrapper) {
|
||||
await waitForPromises();
|
||||
|
||||
localWrapper.find(VueDraggable).vm.$emit('input', reorderedDesigns);
|
||||
localWrapper.find(VueDraggable).vm.$emit('change', {
|
||||
localWrapper.findComponent(VueDraggable).vm.$emit('input', reorderedDesigns);
|
||||
localWrapper.findComponent(VueDraggable).vm.$emit('change', {
|
||||
moved: {
|
||||
newIndex: 0,
|
||||
element: designToMove,
|
||||
|
|
|
@ -44,7 +44,7 @@ describe('Design management router', () => {
|
|||
it('pushes home component', () => {
|
||||
const wrapper = factory(routeArg);
|
||||
|
||||
expect(wrapper.find(Designs).exists()).toBe(true);
|
||||
expect(wrapper.findComponent(Designs).exists()).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -55,7 +55,7 @@ describe('Design management router', () => {
|
|||
const wrapper = factory(routeArg);
|
||||
|
||||
return nextTick().then(() => {
|
||||
const detail = wrapper.find(DesignDetail);
|
||||
const detail = wrapper.findComponent(DesignDetail);
|
||||
expect(detail.exists()).toBe(true);
|
||||
expect(detail.props('id')).toEqual('1');
|
||||
});
|
||||
|
|
|
@ -263,7 +263,7 @@ describe('DiffFileHeader component', () => {
|
|||
},
|
||||
},
|
||||
});
|
||||
expect(findModeChangedLine().exists()).toBeFalsy();
|
||||
expect(findModeChangedLine().exists()).toBe(false);
|
||||
},
|
||||
);
|
||||
|
||||
|
|
|
@ -79,7 +79,7 @@ describe('CommitMessageField', () => {
|
|||
await fillText(text);
|
||||
|
||||
expect(findHighlightsText().text()).toEqual(text);
|
||||
expect(findHighlightsMark().text()).toBeFalsy();
|
||||
expect(findHighlightsMark().text()).toBe('');
|
||||
});
|
||||
|
||||
it('highlights characters over 50 length', async () => {
|
||||
|
|
|
@ -60,8 +60,8 @@ describe('IDE store file actions', () => {
|
|||
|
||||
it('closes open files', () => {
|
||||
return store.dispatch('closeFile', localFile).then(() => {
|
||||
expect(localFile.opened).toBeFalsy();
|
||||
expect(localFile.active).toBeFalsy();
|
||||
expect(localFile.opened).toBe(false);
|
||||
expect(localFile.active).toBe(false);
|
||||
expect(store.state.openFiles.length).toBe(0);
|
||||
});
|
||||
});
|
||||
|
@ -269,7 +269,7 @@ describe('IDE store file actions', () => {
|
|||
|
||||
it('sets the file as active', () => {
|
||||
return store.dispatch('getFileData', { path: localFile.path }).then(() => {
|
||||
expect(localFile.active).toBeTruthy();
|
||||
expect(localFile.active).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -277,7 +277,7 @@ describe('IDE store file actions', () => {
|
|||
return store
|
||||
.dispatch('getFileData', { path: localFile.path, makeFileActive: false })
|
||||
.then(() => {
|
||||
expect(localFile.active).toBeFalsy();
|
||||
expect(localFile.active).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -71,7 +71,7 @@ describe('Author Select', () => {
|
|||
wrapper.setData({ hasSearchParam: true });
|
||||
|
||||
await nextTick();
|
||||
expect(findDropdownContainer().attributes('disabled')).toBe(undefined);
|
||||
expect(findDropdownContainer().attributes('disabled')).toBeUndefined();
|
||||
});
|
||||
|
||||
it('has correct tooltip message', async () => {
|
||||
|
@ -91,7 +91,7 @@ describe('Author Select', () => {
|
|||
wrapper.setData({ hasSearchParam: false });
|
||||
|
||||
await nextTick();
|
||||
expect(findDropdown().attributes('disabled')).toBe(undefined);
|
||||
expect(findDropdown().attributes('disabled')).toBeUndefined();
|
||||
});
|
||||
|
||||
it('hasSearchParam if user types a truthy string', () => {
|
||||
|
|
|
@ -26,11 +26,11 @@ describe('Wip', () => {
|
|||
it('should have props', () => {
|
||||
const { mr, service } = WorkInProgress.props;
|
||||
|
||||
expect(mr.type instanceof Object).toBeTruthy();
|
||||
expect(mr.required).toBeTruthy();
|
||||
expect(mr.type instanceof Object).toBe(true);
|
||||
expect(mr.required).toBe(true);
|
||||
|
||||
expect(service.type instanceof Object).toBeTruthy();
|
||||
expect(service.required).toBeTruthy();
|
||||
expect(service.type instanceof Object).toBe(true);
|
||||
expect(service.required).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -64,7 +64,7 @@ describe('Wip', () => {
|
|||
|
||||
await waitForPromises();
|
||||
|
||||
expect(vm.isMakingRequest).toBeTruthy();
|
||||
expect(vm.isMakingRequest).toBe(true);
|
||||
expect(eventHub.$emit).toHaveBeenCalledWith('UpdateWidgetData', mrObj);
|
||||
expect(toast).toHaveBeenCalledWith('Marked as ready. Merging is now allowed.');
|
||||
});
|
||||
|
@ -81,7 +81,7 @@ describe('Wip', () => {
|
|||
});
|
||||
|
||||
it('should have correct elements', () => {
|
||||
expect(el.classList.contains('mr-widget-body')).toBeTruthy();
|
||||
expect(el.classList.contains('mr-widget-body')).toBe(true);
|
||||
expect(el.innerText).toContain(
|
||||
"Merge blocked: merge request must be marked as ready. It's still marked as draft.",
|
||||
);
|
||||
|
@ -95,7 +95,7 @@ describe('Wip', () => {
|
|||
|
||||
await nextTick();
|
||||
|
||||
expect(el.querySelector('.js-remove-draft')).toEqual(null);
|
||||
expect(el.querySelector('.js-remove-draft')).toBeNull();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -104,7 +104,7 @@ describe('vue_shared/components/confirm_modal', () => {
|
|||
});
|
||||
|
||||
it('renders GlModal with data', () => {
|
||||
expect(findModal().exists()).toBeTruthy();
|
||||
expect(findModal().exists()).toBe(true);
|
||||
expect(findModal().attributes()).toEqual(
|
||||
expect.objectContaining({
|
||||
oktitle: MOCK_MODAL_DATA.modalAttributes.okTitle,
|
||||
|
|
|
@ -234,14 +234,14 @@ describe('RunnerInstructionsModal component', () => {
|
|||
MockResizeObserver.mockResize('xs');
|
||||
await nextTick();
|
||||
|
||||
expect(findPlatformButtonGroup().attributes('vertical')).toBeTruthy();
|
||||
expect(findPlatformButtonGroup().attributes('vertical')).toEqual('true');
|
||||
});
|
||||
|
||||
it('to a non-xs viewport', async () => {
|
||||
MockResizeObserver.mockResize('sm');
|
||||
await nextTick();
|
||||
|
||||
expect(findPlatformButtonGroup().props('vertical')).toBeFalsy();
|
||||
expect(findPlatformButtonGroup().props('vertical')).toBeUndefined();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -3,7 +3,7 @@ import { nextTick } from 'vue';
|
|||
|
||||
import ActionsButton from '~/vue_shared/components/actions_button.vue';
|
||||
import LocalStorageSync from '~/vue_shared/components/local_storage_sync.vue';
|
||||
import WebIdeLink from '~/vue_shared/components/web_ide_link.vue';
|
||||
import WebIdeLink, { i18n } from '~/vue_shared/components/web_ide_link.vue';
|
||||
import ConfirmForkModal from '~/vue_shared/components/confirm_fork_modal.vue';
|
||||
|
||||
import { stubComponent } from 'helpers/stub_component';
|
||||
|
@ -37,8 +37,8 @@ const ACTION_EDIT_CONFIRM_FORK = {
|
|||
const ACTION_WEB_IDE = {
|
||||
href: TEST_WEB_IDE_URL,
|
||||
key: 'webide',
|
||||
secondaryText: 'Quickly and easily edit multiple files in your project.',
|
||||
tooltip: '',
|
||||
secondaryText: i18n.webIdeText,
|
||||
tooltip: i18n.webIdeTooltip,
|
||||
text: 'Web IDE',
|
||||
attrs: {
|
||||
'data-qa-selector': 'web_ide_button',
|
||||
|
|
|
@ -127,7 +127,7 @@ RSpec.describe Gitlab::Auth::AuthFinders do
|
|||
let(:doorkeeper_access_token) { Doorkeeper::AccessToken.create!(application_id: application.id, resource_owner_id: user.id, scopes: 'api') }
|
||||
|
||||
before do
|
||||
set_bearer_token(doorkeeper_access_token.token)
|
||||
set_bearer_token(doorkeeper_access_token.plaintext_token)
|
||||
end
|
||||
|
||||
it { is_expected.to eq user }
|
||||
|
@ -577,7 +577,7 @@ RSpec.describe Gitlab::Auth::AuthFinders do
|
|||
|
||||
context 'passed as header' do
|
||||
before do
|
||||
set_bearer_token(doorkeeper_access_token.token)
|
||||
set_bearer_token(doorkeeper_access_token.plaintext_token)
|
||||
end
|
||||
|
||||
it 'returns token if valid oauth_access_token' do
|
||||
|
@ -587,7 +587,7 @@ RSpec.describe Gitlab::Auth::AuthFinders do
|
|||
|
||||
context 'passed as param' do
|
||||
it 'returns user if valid oauth_access_token' do
|
||||
set_param(:access_token, doorkeeper_access_token.token)
|
||||
set_param(:access_token, doorkeeper_access_token.plaintext_token)
|
||||
|
||||
expect(find_oauth_access_token.token).to eq doorkeeper_access_token.token
|
||||
end
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Gitlab::DoorkeeperSecretStoring::Pbkdf2Sha512 do
|
||||
describe '.transform_secret' do
|
||||
let(:plaintext_token) { 'CzOBzBfU9F-HvsqfTaTXF4ivuuxYZuv3BoAK4pnvmyw' }
|
||||
|
||||
it 'generates a PBKDF2+SHA512 hashed value in the correct format' do
|
||||
expect(described_class.transform_secret(plaintext_token))
|
||||
.to eq("$pbkdf2-sha512$20000$$.c0G5XJVEew1TyeJk5TrkvB0VyOaTmDzPrsdNRED9vVeZlSyuG3G90F0ow23zUCiWKAVwmNnR/ceh.nJG3MdpQ") # rubocop:disable Layout/LineLength
|
||||
end
|
||||
|
||||
context 'when hash_oauth_tokens is disabled' do
|
||||
before do
|
||||
stub_feature_flags(hash_oauth_tokens: false)
|
||||
end
|
||||
|
||||
it 'returns a plaintext token' do
|
||||
expect(described_class.transform_secret(plaintext_token)).to eq(plaintext_token)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'STRETCHES' do
|
||||
it 'is 20_000' do
|
||||
expect(described_class::STRETCHES).to eq(20_000)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'SALT' do
|
||||
it 'is empty' do
|
||||
expect(described_class::SALT).to be_empty
|
||||
end
|
||||
end
|
||||
end
|
|
@ -22,4 +22,51 @@ RSpec.describe OauthAccessToken do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'Doorkeeper secret storing' do
|
||||
it 'stores the token in hashed format' do
|
||||
expect(token.token).not_to eq(token.plaintext_token)
|
||||
end
|
||||
|
||||
it 'does not allow falling back to plaintext token comparison' do
|
||||
expect(described_class.by_token(token.token)).to be_nil
|
||||
end
|
||||
|
||||
it 'finds a token by plaintext token' do
|
||||
expect(described_class.by_token(token.plaintext_token)).to be_a(OauthAccessToken)
|
||||
end
|
||||
|
||||
context 'when the token is stored in plaintext' do
|
||||
let(:plaintext_token) { Devise.friendly_token(20) }
|
||||
|
||||
before do
|
||||
token.update_column(:token, plaintext_token)
|
||||
end
|
||||
|
||||
it 'falls back to plaintext token comparison' do
|
||||
expect(described_class.by_token(plaintext_token)).to be_a(OauthAccessToken)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when hash_oauth_secrets is disabled' do
|
||||
let(:hashed_token) { create(:oauth_access_token, application_id: app_one.id) }
|
||||
|
||||
before do
|
||||
hashed_token
|
||||
stub_feature_flags(hash_oauth_tokens: false)
|
||||
end
|
||||
|
||||
it 'stores the token in plaintext' do
|
||||
expect(token.token).to eq(token.plaintext_token)
|
||||
end
|
||||
|
||||
it 'finds a token by plaintext token' do
|
||||
expect(described_class.by_token(token.plaintext_token)).to be_a(OauthAccessToken)
|
||||
end
|
||||
|
||||
it 'does not find a token that was previously stored as hashed' do
|
||||
expect(described_class.by_token(hashed_token.plaintext_token)).to be_nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -9,13 +9,13 @@ RSpec.describe 'doorkeeper access' do
|
|||
|
||||
describe "unauthenticated" do
|
||||
it "returns authentication success" do
|
||||
get api("/user"), params: { access_token: token.token }
|
||||
get api("/user"), params: { access_token: token.plaintext_token }
|
||||
expect(response).to have_gitlab_http_status(:ok)
|
||||
end
|
||||
|
||||
include_examples 'user login request with unique ip limit' do
|
||||
def request
|
||||
get api('/user'), params: { access_token: token.token }
|
||||
get api('/user'), params: { access_token: token.plaintext_token }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -42,7 +42,7 @@ RSpec.describe 'doorkeeper access' do
|
|||
|
||||
shared_examples 'forbidden request' do
|
||||
it 'returns 403 response' do
|
||||
get api("/user"), params: { access_token: token.token }
|
||||
get api("/user"), params: { access_token: token.plaintext_token }
|
||||
|
||||
expect(response).to have_gitlab_http_status(:forbidden)
|
||||
end
|
||||
|
|
|
@ -376,7 +376,7 @@ RSpec.describe API::GoProxy do
|
|||
end
|
||||
|
||||
it 'returns ok with a job token' do
|
||||
get_resource(oauth_access_token: job)
|
||||
get_resource(access_token: job)
|
||||
|
||||
expect(response).to have_gitlab_http_status(:ok)
|
||||
end
|
||||
|
@ -395,7 +395,7 @@ RSpec.describe API::GoProxy do
|
|||
|
||||
it 'returns unauthorized with a failed job token' do
|
||||
job.update!(status: :failed)
|
||||
get_resource(oauth_access_token: job)
|
||||
get_resource(access_token: job)
|
||||
|
||||
expect(response).to have_gitlab_http_status(:unauthorized)
|
||||
end
|
||||
|
@ -445,7 +445,7 @@ RSpec.describe API::GoProxy do
|
|||
end
|
||||
|
||||
it 'returns not found with a job token' do
|
||||
get_resource(oauth_access_token: job)
|
||||
get_resource(access_token: job)
|
||||
|
||||
expect(response).to have_gitlab_http_status(:not_found)
|
||||
end
|
||||
|
|
|
@ -539,7 +539,7 @@ RSpec.describe API::Helpers do
|
|||
let(:token) { create(:oauth_access_token) }
|
||||
|
||||
before do
|
||||
env['HTTP_AUTHORIZATION'] = "Bearer #{token.token}"
|
||||
env['HTTP_AUTHORIZATION'] = "Bearer #{token.plaintext_token}"
|
||||
end
|
||||
|
||||
it_behaves_like 'sudo'
|
||||
|
|
|
@ -59,7 +59,7 @@ RSpec.describe API::NpmProjectPackages do
|
|||
end
|
||||
|
||||
context 'with access token' do
|
||||
let(:headers) { build_token_auth_header(token.token) }
|
||||
let(:headers) { build_token_auth_header(token.plaintext_token) }
|
||||
|
||||
it_behaves_like 'successfully downloads the file'
|
||||
it_behaves_like 'a package tracking event', 'API::NpmPackages', 'pull_package'
|
||||
|
@ -95,7 +95,7 @@ RSpec.describe API::NpmProjectPackages do
|
|||
it_behaves_like 'a package file that requires auth'
|
||||
|
||||
context 'with guest' do
|
||||
let(:headers) { build_token_auth_header(token.token) }
|
||||
let(:headers) { build_token_auth_header(token.plaintext_token) }
|
||||
|
||||
it 'denies download when not enough permissions' do
|
||||
project.add_guest(user)
|
||||
|
@ -356,7 +356,7 @@ RSpec.describe API::NpmProjectPackages do
|
|||
end
|
||||
|
||||
def upload_with_token(package_name, params = {})
|
||||
upload_package(package_name, params.merge(access_token: token.token))
|
||||
upload_package(package_name, params.merge(access_token: token.plaintext_token))
|
||||
end
|
||||
|
||||
def upload_with_job_token(package_name, params = {})
|
||||
|
|
|
@ -104,8 +104,8 @@ RSpec.describe 'Rack Attack global throttles', :use_clean_rails_memory_store_cac
|
|||
end
|
||||
|
||||
context 'with the token in the OAuth headers' do
|
||||
let(:request_args) { api_get_args_with_token_headers(api_partial_url, oauth_token_headers(token)) }
|
||||
let(:other_user_request_args) { api_get_args_with_token_headers(api_partial_url, oauth_token_headers(other_user_token)) }
|
||||
let(:request_args) { api_get_args_with_token_headers(api_partial_url, bearer_headers(token)) }
|
||||
let(:other_user_request_args) { api_get_args_with_token_headers(api_partial_url, bearer_headers(other_user_token)) }
|
||||
|
||||
it_behaves_like 'rate-limited user based token-authenticated requests'
|
||||
end
|
||||
|
@ -131,8 +131,8 @@ RSpec.describe 'Rack Attack global throttles', :use_clean_rails_memory_store_cac
|
|||
end
|
||||
|
||||
context 'with the token in the OAuth headers' do
|
||||
let(:request_args) { api_get_args_with_token_headers(api_partial_url, oauth_token_headers(token)) }
|
||||
let(:other_user_request_args) { api_get_args_with_token_headers(api_partial_url, oauth_token_headers(other_user_token)) }
|
||||
let(:request_args) { api_get_args_with_token_headers(api_partial_url, bearer_headers(token)) }
|
||||
let(:other_user_request_args) { api_get_args_with_token_headers(api_partial_url, bearer_headers(other_user_token)) }
|
||||
|
||||
it_behaves_like 'rate-limited user based token-authenticated requests'
|
||||
end
|
||||
|
@ -1189,7 +1189,7 @@ RSpec.describe 'Rack Attack global throttles', :use_clean_rails_memory_store_cac
|
|||
it 'request is authenticated by token in the OAuth headers' do
|
||||
expect_authenticated_request
|
||||
|
||||
get url, headers: oauth_token_headers(personal_access_token)
|
||||
get url, headers: bearer_headers(personal_access_token)
|
||||
end
|
||||
|
||||
it 'request is authenticated by token in basic auth' do
|
||||
|
@ -1206,7 +1206,7 @@ RSpec.describe 'Rack Attack global throttles', :use_clean_rails_memory_store_cac
|
|||
it 'request is authenticated by token in query string' do
|
||||
expect_authenticated_request
|
||||
|
||||
get url, params: { access_token: oauth_token.token }
|
||||
get url, params: { access_token: oauth_token.plaintext_token }
|
||||
end
|
||||
|
||||
it 'request is authenticated by token in the headers' do
|
||||
|
|
|
@ -19,15 +19,17 @@ module ApiHelpers
|
|||
# => "/api/v2/issues?foo=bar&private_token=..."
|
||||
#
|
||||
# Returns the relative path to the requested API resource
|
||||
def api(path, user = nil, version: API::API.version, personal_access_token: nil, oauth_access_token: nil, job_token: nil)
|
||||
def api(path, user = nil, version: API::API.version, personal_access_token: nil, oauth_access_token: nil, job_token: nil, access_token: nil)
|
||||
full_path = "/api/#{version}#{path}"
|
||||
|
||||
if oauth_access_token
|
||||
query_string = "access_token=#{oauth_access_token.token}"
|
||||
query_string = "access_token=#{oauth_access_token.plaintext_token}"
|
||||
elsif personal_access_token
|
||||
query_string = "private_token=#{personal_access_token.token}"
|
||||
elsif job_token
|
||||
query_string = "job_token=#{job_token}"
|
||||
elsif access_token
|
||||
query_string = "access_token=#{access_token.token}"
|
||||
elsif user
|
||||
personal_access_token = create(:personal_access_token, user: user)
|
||||
query_string = "private_token=#{personal_access_token.token}"
|
||||
|
|
|
@ -17,8 +17,12 @@ module RackAttackSpecHelpers
|
|||
{ Gitlab::Auth::AuthFinders::PRIVATE_TOKEN_HEADER => personal_access_token.token }
|
||||
end
|
||||
|
||||
def bearer_headers(token)
|
||||
{ 'AUTHORIZATION' => "Bearer #{token.token}" }
|
||||
end
|
||||
|
||||
def oauth_token_headers(oauth_access_token)
|
||||
{ 'AUTHORIZATION' => "Bearer #{oauth_access_token.token}" }
|
||||
{ 'AUTHORIZATION' => "Bearer #{oauth_access_token.plaintext_token}" }
|
||||
end
|
||||
|
||||
def basic_auth_headers(user, personal_access_token)
|
||||
|
|
|
@ -244,7 +244,7 @@ RSpec.shared_examples 'handling get metadata requests' do |scope: :project|
|
|||
let(:headers) do
|
||||
case auth
|
||||
when :oauth
|
||||
build_token_auth_header(token.token)
|
||||
build_token_auth_header(token.plaintext_token)
|
||||
when :personal_access_token
|
||||
build_token_auth_header(personal_access_token.token)
|
||||
when :job_token
|
||||
|
@ -404,7 +404,7 @@ RSpec.shared_examples 'handling get dist tags requests' do |scope: :project|
|
|||
|
||||
shared_examples 'handling all conditions' do
|
||||
context 'with oauth token' do
|
||||
let(:headers) { build_token_auth_header(token.token) }
|
||||
let(:headers) { build_token_auth_header(token.plaintext_token) }
|
||||
|
||||
it_behaves_like 'handling different package names, visibilities and user roles'
|
||||
end
|
||||
|
@ -514,7 +514,7 @@ RSpec.shared_examples 'handling create dist tag requests' do |scope: :project|
|
|||
|
||||
shared_examples 'handling all conditions' do
|
||||
context 'with oauth token' do
|
||||
let(:headers) { build_token_auth_header(token.token) }
|
||||
let(:headers) { build_token_auth_header(token.plaintext_token) }
|
||||
|
||||
it_behaves_like 'handling different package names, visibilities and user roles'
|
||||
end
|
||||
|
@ -622,7 +622,7 @@ RSpec.shared_examples 'handling delete dist tag requests' do |scope: :project|
|
|||
|
||||
shared_examples 'handling all conditions' do
|
||||
context 'with oauth token' do
|
||||
let(:headers) { build_token_auth_header(token.token) }
|
||||
let(:headers) { build_token_auth_header(token.plaintext_token) }
|
||||
|
||||
it_behaves_like 'handling different package names, visibilities and user roles'
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue