Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
d5f67e75b6
commit
cb9b55e662
37 changed files with 283 additions and 76 deletions
|
@ -315,7 +315,7 @@ Dangerfile @gl-quality/eng-prod
|
||||||
/config/dependency_decisions.yml @gitlab-org/legal-reviewers
|
/config/dependency_decisions.yml @gitlab-org/legal-reviewers
|
||||||
|
|
||||||
^[Workhorse]
|
^[Workhorse]
|
||||||
/workhorse/ @jacobvosmaer-gitlab @nolith @patrickbajao
|
/workhorse/ @jacobvosmaer-gitlab @nolith @patrickbajao @igor.drozdov
|
||||||
|
|
||||||
[Application Security]
|
[Application Security]
|
||||||
/app/assets/javascripts/lib/dompurify.js @gitlab-com/gl-security/appsec
|
/app/assets/javascripts/lib/dompurify.js @gitlab-com/gl-security/appsec
|
||||||
|
|
|
@ -49,7 +49,7 @@ export default {
|
||||||
return {
|
return {
|
||||||
maxDateRangeTooltip: sprintf(
|
maxDateRangeTooltip: sprintf(
|
||||||
__(
|
__(
|
||||||
'Showing data for workflow items created in this date range. Date range limited to %{maxDateRange} days.',
|
'Showing data for workflow items completed in this date range. Date range limited to %{maxDateRange} days.',
|
||||||
),
|
),
|
||||||
{
|
{
|
||||||
maxDateRange: this.maxDateRange,
|
maxDateRange: this.maxDateRange,
|
||||||
|
|
|
@ -50,7 +50,12 @@ export default {
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="settings-content">
|
<div class="settings-content">
|
||||||
<branch-rule v-for="rule in branchRules" :key="rule.name" :name="rule.name" />
|
<branch-rule
|
||||||
|
v-for="rule in branchRules"
|
||||||
|
:key="rule.name"
|
||||||
|
:name="rule.name"
|
||||||
|
:branch-protection="rule.branchProtection"
|
||||||
|
/>
|
||||||
|
|
||||||
<span v-if="!branchRules.length" data-testid="empty">{{ $options.i18n.emptyState }}</span>
|
<span v-if="!branchRules.length" data-testid="empty">{{ $options.i18n.emptyState }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -6,6 +6,8 @@ export const i18n = {
|
||||||
defaultLabel: s__('BranchRules|default'),
|
defaultLabel: s__('BranchRules|default'),
|
||||||
protectedLabel: s__('BranchRules|protected'),
|
protectedLabel: s__('BranchRules|protected'),
|
||||||
detailsButtonLabel: s__('BranchRules|Details'),
|
detailsButtonLabel: s__('BranchRules|Details'),
|
||||||
|
allowForcePush: s__('BranchRules|Allowed to force push'),
|
||||||
|
codeOwnerApprovalRequired: s__('BranchRules|Requires CODEOWNERS approval'),
|
||||||
};
|
};
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
@ -35,19 +37,29 @@ export default {
|
||||||
required: false,
|
required: false,
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
approvalDetails: {
|
branchProtection: {
|
||||||
type: Array,
|
type: Object,
|
||||||
required: false,
|
required: false,
|
||||||
default: () => [],
|
default: () => {},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
hasApprovalDetails() {
|
hasApprovalDetails() {
|
||||||
return this.approvalDetails && this.approvalDetails.length;
|
return this.approvalDetails.length;
|
||||||
},
|
},
|
||||||
detailsPath() {
|
detailsPath() {
|
||||||
return `${this.branchRulesPath}?branch=${this.name}`;
|
return `${this.branchRulesPath}?branch=${this.name}`;
|
||||||
},
|
},
|
||||||
|
approvalDetails() {
|
||||||
|
const approvalDetails = [];
|
||||||
|
if (this.branchProtection.allowForcePush) {
|
||||||
|
approvalDetails.push(this.$options.i18n.allowForcePush);
|
||||||
|
}
|
||||||
|
if (this.branchProtection.codeOwnerApprovalRequired) {
|
||||||
|
approvalDetails.push(this.$options.i18n.codeOwnerApprovalRequired);
|
||||||
|
}
|
||||||
|
return approvalDetails;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
@ -69,6 +81,8 @@ export default {
|
||||||
<li v-for="(detail, index) in approvalDetails" :key="index">{{ detail }}</li>
|
<li v-for="(detail, index) in approvalDetails" :key="index">{{ detail }}</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<gl-button :href="detailsPath"> {{ $options.i18n.detailsButtonLabel }}</gl-button>
|
<gl-button class="gl-align-self-start" :href="detailsPath">
|
||||||
|
{{ $options.i18n.detailsButtonLabel }}</gl-button
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -4,6 +4,10 @@ query getBranchRules($projectPath: ID!) {
|
||||||
branchRules {
|
branchRules {
|
||||||
nodes {
|
nodes {
|
||||||
name
|
name
|
||||||
|
branchProtection {
|
||||||
|
allowForcePush
|
||||||
|
codeOwnerApprovalRequired
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,13 @@ module AccessTokensActions
|
||||||
def index
|
def index
|
||||||
@resource_access_token = PersonalAccessToken.new
|
@resource_access_token = PersonalAccessToken.new
|
||||||
set_index_vars
|
set_index_vars
|
||||||
|
|
||||||
|
respond_to do |format|
|
||||||
|
format.html
|
||||||
|
format.json do
|
||||||
|
render json: @active_resource_access_tokens
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
# rubocop:enable Gitlab/ModuleWithInstanceVariables
|
# rubocop:enable Gitlab/ModuleWithInstanceVariables
|
||||||
|
|
||||||
|
@ -68,9 +75,31 @@ module AccessTokensActions
|
||||||
|
|
||||||
def active_resource_access_tokens
|
def active_resource_access_tokens
|
||||||
tokens = finder(state: 'active', sort: 'expires_at_asc_id_desc').execute.preload_users
|
tokens = finder(state: 'active', sort: 'expires_at_asc_id_desc').execute.preload_users
|
||||||
|
|
||||||
|
if Feature.enabled?('access_token_pagination')
|
||||||
|
tokens = tokens.page(page)
|
||||||
|
add_pagination_headers(tokens)
|
||||||
|
end
|
||||||
|
|
||||||
represent(tokens)
|
represent(tokens)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def add_pagination_headers(relation)
|
||||||
|
Gitlab::Pagination::OffsetHeaderBuilder.new(
|
||||||
|
request_context: self,
|
||||||
|
per_page: relation.limit_value,
|
||||||
|
page: relation.current_page,
|
||||||
|
next_page: relation.next_page,
|
||||||
|
prev_page: relation.prev_page,
|
||||||
|
total: relation.total_count,
|
||||||
|
params: params.permit(:page)
|
||||||
|
).execute
|
||||||
|
end
|
||||||
|
|
||||||
|
def page
|
||||||
|
(params[:page] || 1).to_i
|
||||||
|
end
|
||||||
|
|
||||||
def finder(options = {})
|
def finder(options = {})
|
||||||
PersonalAccessTokensFinder.new({ user: bot_users, impersonation: false }.merge(options))
|
PersonalAccessTokensFinder.new({ user: bot_users, impersonation: false }.merge(options))
|
||||||
end
|
end
|
||||||
|
|
|
@ -295,7 +295,7 @@ Find this content in the [Container Registry troubleshooting documentation](../p
|
||||||
|
|
||||||
## Sidekiq
|
## Sidekiq
|
||||||
|
|
||||||
This content has been moved to [Troubleshooting Sidekiq](sidekiq.md).
|
This content has been moved to [Troubleshooting Sidekiq](../sidekiq/sidekiq_troubleshooting.md).
|
||||||
|
|
||||||
## Geo
|
## Geo
|
||||||
|
|
||||||
|
|
|
@ -361,6 +361,31 @@ hierarchy. Choosing a proper solution will require a thoughtful research.
|
||||||
1. Maintain consistent features and behavior across SaaS and self-managed codebase.
|
1. Maintain consistent features and behavior across SaaS and self-managed codebase.
|
||||||
1. Be mindful about a cognitive load added by the hierarchical limits, aim to reduce it.
|
1. Be mindful about a cognitive load added by the hierarchical limits, aim to reduce it.
|
||||||
|
|
||||||
|
## Phases and iterations
|
||||||
|
|
||||||
|
**Phase 1**: Compile examples of current most important application limits — Owning Team
|
||||||
|
a. Owning Team (in collaboration with Stage Groups) compiles a list of the
|
||||||
|
most important application limits used in Rails today.
|
||||||
|
**Phase 2**: Implement Rate Limiting Framework in Rails – Owning Team
|
||||||
|
a. Triangulate rate limiting abstractions based on the data gathered in Phase 1
|
||||||
|
b. Develop YAML model for limits.
|
||||||
|
c. Build Rails SDK.
|
||||||
|
d. Create examples showcasing usage of the new rate limits SDK.
|
||||||
|
**Phase 3**: Team Fanout of Rails SDK – Stage Groups
|
||||||
|
a. Individual stage groups begin using the SDK built in Phase 2 for new limit and policies.
|
||||||
|
b. Stage groups begin replacing historical ad-hoc limit implementations with the SDK.
|
||||||
|
c. Provides means to monitor and observe the progress of the replacement effort. Ideally this is broken down to the `feature_category` level to drive group-level buy-in -- Owning Team.
|
||||||
|
**Phase 4**: Enable Satellite Services to Use the Rate Limiting Framework – Owning Team
|
||||||
|
a. Determine if the goals of Phase 4 are best met by either
|
||||||
|
1. Extracting the Rails rate limiting service into a decoupled service OR
|
||||||
|
2. Implementing a separate Go library which uses the same backend (eg, Redis) for rate limiting.
|
||||||
|
**Phase 5**: SDK for Satellite Services – Owning Team
|
||||||
|
a. Build Golang SDK.
|
||||||
|
c. Create examples showcasing usage of the new rate limits SDK.
|
||||||
|
**Phase 6**: Team Fanout for Satellite Services – Stage Groups
|
||||||
|
a. Individual stage groups being using the SDK built in Phase 5 for new limit and policies.
|
||||||
|
b. Stage groups begin replacing historical ad hoc limit implementations with the SDK.
|
||||||
|
|
||||||
## Status
|
## Status
|
||||||
|
|
||||||
Request For Comments.
|
Request For Comments.
|
||||||
|
@ -373,6 +398,7 @@ Request For Comments.
|
||||||
- 2022-07-06: A fourth, [consolidated proposal](https://gitlab.com/gitlab-org/gitlab/-/issues/364524#note_1017640650), has been submitted.
|
- 2022-07-06: A fourth, [consolidated proposal](https://gitlab.com/gitlab-org/gitlab/-/issues/364524#note_1017640650), has been submitted.
|
||||||
- 2022-07-12: Started working on the design document following [Architecture Evolution Workflow](https://about.gitlab.com/handbook/engineering/architecture/workflow/).
|
- 2022-07-12: Started working on the design document following [Architecture Evolution Workflow](https://about.gitlab.com/handbook/engineering/architecture/workflow/).
|
||||||
- 2022-09-08: The initial version of the blueprint has been merged.
|
- 2022-09-08: The initial version of the blueprint has been merged.
|
||||||
|
- 2022-09-21: Plan for phases and iterations has been established.
|
||||||
|
|
||||||
## Who
|
## Who
|
||||||
|
|
||||||
|
|
|
@ -49,9 +49,11 @@ bundle exec rake db:reset RAILS_ENV=test
|
||||||
|
|
||||||
- `bundle exec rake db:migrate RAILS_ENV=development`: Execute any pending migrations that you may have picked up from a MR
|
- `bundle exec rake db:migrate RAILS_ENV=development`: Execute any pending migrations that you may have picked up from a MR
|
||||||
- `bundle exec rake db:migrate:status RAILS_ENV=development`: Check if all migrations are `up` or `down`
|
- `bundle exec rake db:migrate:status RAILS_ENV=development`: Check if all migrations are `up` or `down`
|
||||||
- `bundle exec rake db:migrate:down VERSION=20170926203418 RAILS_ENV=development`: Tear down a migration
|
- `bundle exec rake db:migrate:down:main VERSION=20170926203418 RAILS_ENV=development`: Tear down a migration
|
||||||
- `bundle exec rake db:migrate:up VERSION=20170926203418 RAILS_ENV=development`: Set up a migration
|
- `bundle exec rake db:migrate:up:main VERSION=20170926203418 RAILS_ENV=development`: Set up a migration
|
||||||
- `bundle exec rake db:migrate:redo VERSION=20170926203418 RAILS_ENV=development`: Re-run a specific migration
|
- `bundle exec rake db:migrate:redo:main VERSION=20170926203418 RAILS_ENV=development`: Re-run a specific migration
|
||||||
|
|
||||||
|
Replace `main` in the above commands to execute agains the `ci` database instead of `main`.
|
||||||
|
|
||||||
## Manually access the database
|
## Manually access the database
|
||||||
|
|
||||||
|
|
|
@ -77,15 +77,6 @@ microservices-based distributed systems - and displays results within GitLab.
|
||||||
|
|
||||||
- [Trace the performance and health](tracing.md) of a deployed application.
|
- [Trace the performance and health](tracing.md) of a deployed application.
|
||||||
|
|
||||||
<!--- start_remove The following content will be removed on remove_date: '2022-10-18'--->
|
|
||||||
|
|
||||||
## Aggregate and store logs (removed) **(FREE SELF)**
|
|
||||||
|
|
||||||
This feature was [deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/346485) in GitLab 14.7
|
|
||||||
and [removed](https://gitlab.com/gitlab-org/gitlab/-/issues/360193) in GitLab 15.2.
|
|
||||||
|
|
||||||
<!--- end_remove -->
|
|
||||||
|
|
||||||
## Manage your infrastructure in code
|
## Manage your infrastructure in code
|
||||||
|
|
||||||
GitLab stores and executes your infrastructure as code, whether it's
|
GitLab stores and executes your infrastructure as code, whether it's
|
||||||
|
|
|
@ -148,7 +148,7 @@ suggested if this feature is used.
|
||||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/208976) in GitLab 12.9.
|
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/208976) in GitLab 12.9.
|
||||||
|
|
||||||
You can edit existing additional custom metrics for your dashboard by selecting the
|
You can edit existing additional custom metrics for your dashboard by selecting the
|
||||||
**{ellipsis_v}** **More actions** dropdown and selecting **Edit metric**.
|
**{ellipsis_v}** **More actions** dropdown list and selecting **Edit metric**.
|
||||||
|
|
||||||
![Edit metric](img/prometheus_dashboard_edit_metric_link_v_12_9.png)
|
![Edit metric](img/prometheus_dashboard_edit_metric_link_v_12_9.png)
|
||||||
|
|
||||||
|
@ -158,7 +158,7 @@ You can edit existing additional custom metrics for your dashboard by selecting
|
||||||
|
|
||||||
You can use keyboard shortcuts to interact more quickly with your currently-focused
|
You can use keyboard shortcuts to interact more quickly with your currently-focused
|
||||||
chart panel. To activate keyboard shortcuts, use keyboard tabs to highlight the
|
chart panel. To activate keyboard shortcuts, use keyboard tabs to highlight the
|
||||||
**{ellipsis_v}** **More actions** dropdown menu, or hover over the dropdown menu
|
**{ellipsis_v}** **More actions** dropdown list, or hover over the dropdown list
|
||||||
with your mouse, then press the key corresponding to your desired action:
|
with your mouse, then press the key corresponding to your desired action:
|
||||||
|
|
||||||
- **Expand panel** - <kbd>e</kbd>
|
- **Expand panel** - <kbd>e</kbd>
|
||||||
|
|
|
@ -17,7 +17,7 @@ Users are locked after ten failed sign-in attempts. These users remain locked:
|
||||||
1. On the top bar, select **Main menu > Admin**.
|
1. On the top bar, select **Main menu > Admin**.
|
||||||
1. On the left sidebar, select **Overview > Users**.
|
1. On the left sidebar, select **Overview > Users**.
|
||||||
1. Use the search bar to find the locked user.
|
1. Use the search bar to find the locked user.
|
||||||
1. From the **User administration** dropdown select **Unlock**.
|
1. From the **User administration** dropdown list select **Unlock**.
|
||||||
|
|
||||||
![Unlock a user from the Admin Area](img/unlock_user_v14_7.png)
|
![Unlock a user from the Admin Area](img/unlock_user_v14_7.png)
|
||||||
|
|
||||||
|
|
|
@ -309,6 +309,10 @@ locked. Projects can only be unlocked by purchasing more storage subscription un
|
||||||
|
|
||||||
### Purchase more storage and transfer
|
### Purchase more storage and transfer
|
||||||
|
|
||||||
|
Prerequisite:
|
||||||
|
|
||||||
|
- You must have at least the Owner role.
|
||||||
|
|
||||||
You can purchase a storage subscription for your personal or group namespace.
|
You can purchase a storage subscription for your personal or group namespace.
|
||||||
|
|
||||||
NOTE:
|
NOTE:
|
||||||
|
@ -324,9 +328,9 @@ You can [cancel the subscription](#enable-or-disable-automatic-subscription-rene
|
||||||
1. Select **Purchase more storage** and you are taken to the Customers Portal.
|
1. Select **Purchase more storage** and you are taken to the Customers Portal.
|
||||||
1. Select **Add new subscription**.
|
1. Select **Add new subscription**.
|
||||||
1. Scroll to **Purchase add-on subscriptions** and select **Buy storage subscription**.
|
1. Scroll to **Purchase add-on subscriptions** and select **Buy storage subscription**.
|
||||||
1. In the **Subscription details** section select the name of the user or group from the dropdown.
|
1. In the **Subscription details** section select the name of the user or group from the dropdown list.
|
||||||
1. Enter the desired quantity of storage packs.
|
1. Enter the desired quantity of storage packs.
|
||||||
1. In the **Billing information** section select the payment method from the dropdown.
|
1. In the **Billing information** section select the payment method from the dropdown list.
|
||||||
1. Select the **Privacy Policy** and **Terms of Service** checkbox.
|
1. Select the **Privacy Policy** and **Terms of Service** checkbox.
|
||||||
1. Select **Buy subscription**.
|
1. Select **Buy subscription**.
|
||||||
1. Sign out of the Customers Portal.
|
1. Sign out of the Customers Portal.
|
||||||
|
|
|
@ -151,7 +151,7 @@ To change the namespace linked to a subscription:
|
||||||
[linked](#change-the-linked-account) GitLab SaaS account.
|
[linked](#change-the-linked-account) GitLab SaaS account.
|
||||||
1. Navigate to the **Manage Purchases** page.
|
1. Navigate to the **Manage Purchases** page.
|
||||||
1. Select **Change linked namespace**.
|
1. Select **Change linked namespace**.
|
||||||
1. Select the desired group from the **This subscription is for** dropdown. For a group to appear
|
1. Select the desired group from the **This subscription is for** dropdown list. For a group to appear
|
||||||
here, you must have the Owner role
|
here, you must have the Owner role
|
||||||
for that group.
|
for that group.
|
||||||
1. Select **Proceed to checkout**.
|
1. Select **Proceed to checkout**.
|
||||||
|
|
|
@ -159,7 +159,7 @@ Consider an example upstream project, `git@gitlab.com:gitlab-tests/test-git-lfs-
|
||||||
|
|
||||||
1. Navigate to your project's **Settings > Repository** and
|
1. Navigate to your project's **Settings > Repository** and
|
||||||
expand **Protected branches**.
|
expand **Protected branches**.
|
||||||
1. Select the default branch from the **Branch** dropdown menu,
|
1. Select the default branch from the **Branch** dropdown list,
|
||||||
and set up the
|
and set up the
|
||||||
**Allowed to push** and **Allowed to merge** rules.
|
**Allowed to push** and **Allowed to merge** rules.
|
||||||
1. Select **Protect**.
|
1. Select **Protect**.
|
||||||
|
|
|
@ -136,15 +136,15 @@ For each user, the following are listed:
|
||||||
1. Date of last activity
|
1. Date of last activity
|
||||||
|
|
||||||
To edit a user, select the **Edit** button in that user's
|
To edit a user, select the **Edit** button in that user's
|
||||||
row. To delete the user, or delete the user and their contributions, select the cog dropdown in
|
row. To delete the user, or delete the user and their contributions, select the cog dropdown list in
|
||||||
that user's row, and select the desired option.
|
that user's row, and select the desired option.
|
||||||
|
|
||||||
To change the sort order:
|
To change the sort order:
|
||||||
|
|
||||||
1. Select the sort dropdown.
|
1. Select the sort dropdown list.
|
||||||
1. Select the desired order.
|
1. Select the desired order.
|
||||||
|
|
||||||
By default the sort dropdown shows **Name**.
|
By default the sort dropdown list shows **Name**.
|
||||||
|
|
||||||
To search for users, enter your criteria in the search field. The user search is case
|
To search for users, enter your criteria in the search field. The user search is case
|
||||||
insensitive, and applies partial matching to name and username. To search for an email address,
|
insensitive, and applies partial matching to name and username. To search for an email address,
|
||||||
|
@ -260,7 +260,7 @@ number of members, and whether the group is private, internal, or public. To edi
|
||||||
the **Edit** button in that group's row. To delete the group, select the **Delete** button in
|
the **Edit** button in that group's row. To delete the group, select the **Delete** button in
|
||||||
that group's row.
|
that group's row.
|
||||||
|
|
||||||
To change the sort order, select the sort dropdown and select the desired order. The default
|
To change the sort order, select the sort dropdown list and select the desired order. The default
|
||||||
sort order is by **Last created**.
|
sort order is by **Last created**.
|
||||||
|
|
||||||
To search for groups by name, enter your criteria in the search field. The group search is case
|
To search for groups by name, enter your criteria in the search field. The group search is case
|
||||||
|
|
|
@ -54,7 +54,7 @@ To approve or reject a user sign up:
|
||||||
1. On the left sidebar, select **Overview > Users**.
|
1. On the left sidebar, select **Overview > Users**.
|
||||||
1. Select the **Pending approval** tab.
|
1. Select the **Pending approval** tab.
|
||||||
1. Optional. Select a user.
|
1. Optional. Select a user.
|
||||||
1. Select the **{settings}** **User administration** dropdown.
|
1. Select the **{settings}** **User administration** dropdown list.
|
||||||
1. Select **Approve** or **Reject**.
|
1. Select **Approve** or **Reject**.
|
||||||
|
|
||||||
Approving a user:
|
Approving a user:
|
||||||
|
@ -78,7 +78,7 @@ by removing them in LDAP, or directly from the Admin Area. To do this:
|
||||||
1. On the top bar, select **Main menu > Admin**.
|
1. On the top bar, select **Main menu > Admin**.
|
||||||
1. On the left sidebar, select **Overview > Users**.
|
1. On the left sidebar, select **Overview > Users**.
|
||||||
1. Optional. Select a user.
|
1. Optional. Select a user.
|
||||||
1. Select the **{settings}** **User administration** dropdown.
|
1. Select the **{settings}** **User administration** dropdown list.
|
||||||
1. Select **Block**.
|
1. Select **Block**.
|
||||||
|
|
||||||
A blocked user:
|
A blocked user:
|
||||||
|
@ -102,7 +102,7 @@ A blocked user can be unblocked from the Admin Area. To do this:
|
||||||
1. On the left sidebar, select **Overview > Users**.
|
1. On the left sidebar, select **Overview > Users**.
|
||||||
1. Select the **Blocked** tab.
|
1. Select the **Blocked** tab.
|
||||||
1. Optional. Select a user.
|
1. Optional. Select a user.
|
||||||
1. Select the **{settings}** **User administration** dropdown.
|
1. Select the **{settings}** **User administration** dropdown list.
|
||||||
1. Select **Unblock**.
|
1. Select **Unblock**.
|
||||||
|
|
||||||
The user's state is set to active and they consume a
|
The user's state is set to active and they consume a
|
||||||
|
@ -156,7 +156,7 @@ A user can be deactivated from the Admin Area. To do this:
|
||||||
1. On the top bar, select **Main menu > Admin**.
|
1. On the top bar, select **Main menu > Admin**.
|
||||||
1. On the left sidebar, select **Overview > Users**.
|
1. On the left sidebar, select **Overview > Users**.
|
||||||
1. Optional. Select a user.
|
1. Optional. Select a user.
|
||||||
1. Select the **{settings}** **User administration** dropdown.
|
1. Select the **{settings}** **User administration** dropdown list.
|
||||||
1. Select **Deactivate**.
|
1. Select **Deactivate**.
|
||||||
|
|
||||||
For the deactivation option to be visible to an administrator, the user:
|
For the deactivation option to be visible to an administrator, the user:
|
||||||
|
@ -203,7 +203,7 @@ To do this:
|
||||||
1. On the left sidebar, select **Overview > Users**.
|
1. On the left sidebar, select **Overview > Users**.
|
||||||
1. Select the **Deactivated** tab.
|
1. Select the **Deactivated** tab.
|
||||||
1. Optional. Select a user.
|
1. Optional. Select a user.
|
||||||
1. Select the **{settings}** **User administration** dropdown.
|
1. Select the **{settings}** **User administration** dropdown list.
|
||||||
1. Select **Activate**.
|
1. Select **Activate**.
|
||||||
|
|
||||||
The user's state is set to active and they consume a
|
The user's state is set to active and they consume a
|
||||||
|
|
|
@ -45,7 +45,7 @@ By default both administrators and anyone with the **Owner** role can delete a p
|
||||||
1. Expand the **Visibility and access controls** section.
|
1. Expand the **Visibility and access controls** section.
|
||||||
1. Scroll to:
|
1. Scroll to:
|
||||||
- (GitLab 15.1 and later) **Allowed to delete projects**, and select **Administrators**.
|
- (GitLab 15.1 and later) **Allowed to delete projects**, and select **Administrators**.
|
||||||
- (GitLab 15.0 and earlier) **Default project deletion projection** and select **Only admins can delete project**.
|
- (GitLab 15.0 and earlier) **Default project deletion protection** and select **Only admins can delete project**.
|
||||||
1. Select **Save changes**.
|
1. Select **Save changes**.
|
||||||
|
|
||||||
## Deletion protection **(PREMIUM SELF)**
|
## Deletion protection **(PREMIUM SELF)**
|
||||||
|
@ -82,8 +82,8 @@ To configure delayed project deletion:
|
||||||
1. On the left sidebar, select **Settings > General**.
|
1. On the left sidebar, select **Settings > General**.
|
||||||
1. Expand the **Visibility and access controls** section.
|
1. Expand the **Visibility and access controls** section.
|
||||||
1. Scroll to:
|
1. Scroll to:
|
||||||
- (GitLab 15.1 and later) **Deletion projection** and select keep deleted groups and projects, and select a retention period.
|
- (GitLab 15.1 and later) **Deletion protection** and select keep deleted groups and projects, and select a retention period.
|
||||||
- (GitLab 15.0 and earlier) **Default delayed project projection** and select **Enable delayed project deletion by
|
- (GitLab 15.0 and earlier) **Default delayed project protection** and select **Enable delayed project deletion by
|
||||||
default for newly-created groups.** Then set a retention period in **Default deletion delay**.
|
default for newly-created groups.** Then set a retention period in **Default deletion delay**.
|
||||||
1. Select **Save changes**.
|
1. Select **Save changes**.
|
||||||
|
|
||||||
|
|
|
@ -325,6 +325,9 @@ Use case: If you have multiple users using their own GitHub credentials to set u
|
||||||
repository mirroring, mirroring breaks when people leave the company. Use this
|
repository mirroring, mirroring breaks when people leave the company. Use this
|
||||||
script to migrate disparate mirroring users and tokens into a single service account:
|
script to migrate disparate mirroring users and tokens into a single service account:
|
||||||
|
|
||||||
|
WARNING:
|
||||||
|
Any command that changes data directly could be damaging if not run correctly, or under the right conditions. We highly recommend running them in a test environment with a backup of the instance ready to be restored, just in case.
|
||||||
|
|
||||||
```ruby
|
```ruby
|
||||||
svc_user = User.find_by(username: 'ourServiceUser')
|
svc_user = User.find_by(username: 'ourServiceUser')
|
||||||
token = 'githubAccessToken'
|
token = 'githubAccessToken'
|
||||||
|
|
|
@ -5,6 +5,7 @@ module API
|
||||||
module Internal
|
module Internal
|
||||||
class Pages < ::API::Base
|
class Pages < ::API::Base
|
||||||
feature_category :pages
|
feature_category :pages
|
||||||
|
urgency :low
|
||||||
|
|
||||||
before do
|
before do
|
||||||
authenticate_gitlab_pages_request!
|
authenticate_gitlab_pages_request!
|
||||||
|
|
|
@ -424,7 +424,7 @@ module API
|
||||||
end
|
end
|
||||||
|
|
||||||
desc 'Check pages access of this project'
|
desc 'Check pages access of this project'
|
||||||
get ':id/pages_access', feature_category: :pages do
|
get ':id/pages_access', urgency: :low, feature_category: :pages do
|
||||||
authorize! :read_pages_content, user_project unless user_project.public_pages?
|
authorize! :read_pages_content, user_project unless user_project.public_pages?
|
||||||
status 200
|
status 200
|
||||||
end
|
end
|
||||||
|
|
|
@ -26,7 +26,7 @@ variables:
|
||||||
before_script:
|
before_script:
|
||||||
- apt-get update -qq && apt-get install -y -qq unzip
|
- apt-get update -qq && apt-get install -y -qq unzip
|
||||||
- curl -sSL https://get.sdkman.io | bash
|
- curl -sSL https://get.sdkman.io | bash
|
||||||
- echo sdkman_auto_answer=true > ~/.sdkman/etc/config
|
- echo sdkman_auto_answer=true >> ~/.sdkman/etc/config
|
||||||
- source ~/.sdkman/bin/sdkman-init.sh
|
- source ~/.sdkman/bin/sdkman-init.sh
|
||||||
- sdk install gradle $GRADLE_VERSION < /dev/null
|
- sdk install gradle $GRADLE_VERSION < /dev/null
|
||||||
- sdk use gradle $GRADLE_VERSION
|
- sdk use gradle $GRADLE_VERSION
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
variables:
|
variables:
|
||||||
AUTO_BUILD_IMAGE_VERSION: 'v1.19.0'
|
AUTO_BUILD_IMAGE_VERSION: 'v1.21.0'
|
||||||
|
|
||||||
build:
|
build:
|
||||||
stage: build
|
stage: build
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
variables:
|
variables:
|
||||||
AUTO_BUILD_IMAGE_VERSION: 'v1.19.0'
|
AUTO_BUILD_IMAGE_VERSION: 'v1.21.0'
|
||||||
|
|
||||||
build:
|
build:
|
||||||
stage: build
|
stage: build
|
||||||
|
|
|
@ -21,7 +21,7 @@ module Gitlab
|
||||||
# Note: This diverges from the Sidekiq implementation in 6.4.2 to address a bug where the poll interval wouldn't
|
# Note: This diverges from the Sidekiq implementation in 6.4.2 to address a bug where the poll interval wouldn't
|
||||||
# scale properly when the process count changes, and to take into account the `cron_poll_interval` setting. See
|
# scale properly when the process count changes, and to take into account the `cron_poll_interval` setting. See
|
||||||
# https://gitlab.com/gitlab-org/gitlab/-/merge_requests/99030#note_1117078517 for more details
|
# https://gitlab.com/gitlab-org/gitlab/-/merge_requests/99030#note_1117078517 for more details
|
||||||
Sidekiq.options[:cron_poll_interval] || Sidekiq.options[:poll_interval_average] || scaled_poll_interval
|
Gitlab.config.cron_jobs.poll_interval || Sidekiq.options[:poll_interval_average] || scaled_poll_interval
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -6843,6 +6843,9 @@ msgstr ""
|
||||||
msgid "BranchRules|Allow all users with push access to %{linkStart}force push%{linkEnd}."
|
msgid "BranchRules|Allow all users with push access to %{linkStart}force push%{linkEnd}."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "BranchRules|Allowed to force push"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "BranchRules|Allowed to merge"
|
msgid "BranchRules|Allowed to merge"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -6918,6 +6921,9 @@ msgstr ""
|
||||||
msgid "BranchRules|Required approvals (%{total})"
|
msgid "BranchRules|Required approvals (%{total})"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "BranchRules|Requires CODEOWNERS approval"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "BranchRules|Roles"
|
msgid "BranchRules|Roles"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -37684,7 +37690,7 @@ msgstr ""
|
||||||
msgid "Showing all issues"
|
msgid "Showing all issues"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Showing data for workflow items created in this date range. Date range limited to %{maxDateRange} days."
|
msgid "Showing data for workflow items completed in this date range. Date range limited to %{maxDateRange} days."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Showing graphs based on events of the last %{timerange} days."
|
msgid "Showing graphs based on events of the last %{timerange} days."
|
||||||
|
@ -40742,7 +40748,7 @@ msgstr ""
|
||||||
msgid "The specified tab is invalid, please select another"
|
msgid "The specified tab is invalid, please select another"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "The start date must be ealier than the end date."
|
msgid "The start date must be earlier than the end date."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "The subject will be used as the title of the new issue, and the message will be the description. %{quickActionsLinkStart}Quick actions%{quickActionsLinkEnd} and styling with %{markdownLinkStart}Markdown%{markdownLinkEnd} are supported."
|
msgid "The subject will be used as the title of the new issue, and the message will be the description. %{quickActionsLinkStart}Quick actions%{quickActionsLinkEnd} and styling with %{markdownLinkStart}Markdown%{markdownLinkEnd} are supported."
|
||||||
|
|
|
@ -77,7 +77,7 @@ describe('Daterange component', () => {
|
||||||
it('sets the tooltip', () => {
|
it('sets the tooltip', () => {
|
||||||
const tooltip = findDaterangePicker().props('tooltip');
|
const tooltip = findDaterangePicker().props('tooltip');
|
||||||
expect(tooltip).toBe(
|
expect(tooltip).toBe(
|
||||||
'Showing data for workflow items created in this date range. Date range limited to 30 days.',
|
'Showing data for workflow items completed in this date range. Date range limited to 30 days.',
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -52,6 +52,10 @@ describe('Branch rules app', () => {
|
||||||
|
|
||||||
expect(findAllBranchRules().at(0).props('name')).toBe(nodes[0].name);
|
expect(findAllBranchRules().at(0).props('name')).toBe(nodes[0].name);
|
||||||
|
|
||||||
|
expect(findAllBranchRules().at(0).props('branchProtection')).toEqual(nodes[0].branchProtection);
|
||||||
|
|
||||||
expect(findAllBranchRules().at(1).props('name')).toBe(nodes[1].name);
|
expect(findAllBranchRules().at(1).props('name')).toBe(nodes[1].name);
|
||||||
|
|
||||||
|
expect(findAllBranchRules().at(1).props('branchProtection')).toEqual(nodes[1].branchProtection);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -2,7 +2,11 @@ import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
|
||||||
import BranchRule, {
|
import BranchRule, {
|
||||||
i18n,
|
i18n,
|
||||||
} from '~/projects/settings/repository/branch_rules/components/branch_rule.vue';
|
} from '~/projects/settings/repository/branch_rules/components/branch_rule.vue';
|
||||||
import { branchRuleProvideMock, branchRulePropsMock } from '../mock_data';
|
import {
|
||||||
|
branchRuleProvideMock,
|
||||||
|
branchRulePropsMock,
|
||||||
|
branchRuleWithoutDetailsPropsMock,
|
||||||
|
} from '../mock_data';
|
||||||
|
|
||||||
describe('Branch rule', () => {
|
describe('Branch rule', () => {
|
||||||
let wrapper;
|
let wrapper;
|
||||||
|
@ -45,17 +49,13 @@ describe('Branch rule', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('does not render the protection details list of no details are present', () => {
|
it('does not render the protection details list of no details are present', () => {
|
||||||
createComponent({ approvalDetails: null });
|
createComponent(branchRuleWithoutDetailsPropsMock);
|
||||||
expect(findProtectionDetailsList().exists()).toBe(false);
|
expect(findProtectionDetailsList().exists()).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('renders the protection details list items', () => {
|
it('renders the protection details list items', () => {
|
||||||
expect(findProtectionDetailsListItems().at(0).text()).toBe(
|
expect(findProtectionDetailsListItems().at(0).text()).toBe(wrapper.vm.approvalDetails[0]);
|
||||||
branchRulePropsMock.approvalDetails[0],
|
expect(findProtectionDetailsListItems().at(1).text()).toBe(wrapper.vm.approvalDetails[1]);
|
||||||
);
|
|
||||||
expect(findProtectionDetailsListItems().at(1).text()).toBe(
|
|
||||||
branchRulePropsMock.approvalDetails[1],
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('renders a detail button with the correct href', () => {
|
it('renders a detail button with the correct href', () => {
|
||||||
|
|
|
@ -8,10 +8,18 @@ export const branchRulesMockResponse = {
|
||||||
nodes: [
|
nodes: [
|
||||||
{
|
{
|
||||||
name: 'main',
|
name: 'main',
|
||||||
|
branchProtection: {
|
||||||
|
allowForcePush: true,
|
||||||
|
codeOwnerApprovalRequired: true,
|
||||||
|
},
|
||||||
__typename: 'BranchRule',
|
__typename: 'BranchRule',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'test-*',
|
name: 'test-*',
|
||||||
|
branchProtection: {
|
||||||
|
allowForcePush: false,
|
||||||
|
codeOwnerApprovalRequired: false,
|
||||||
|
},
|
||||||
__typename: 'BranchRule',
|
__typename: 'BranchRule',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -32,5 +40,18 @@ export const branchRulePropsMock = {
|
||||||
name: 'main',
|
name: 'main',
|
||||||
isDefault: true,
|
isDefault: true,
|
||||||
isProtected: true,
|
isProtected: true,
|
||||||
approvalDetails: ['requires approval from TEST', '2 status checks'],
|
branchProtection: {
|
||||||
|
allowForcePush: true,
|
||||||
|
codeOwnerApprovalRequired: true,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export const branchRuleWithoutDetailsPropsMock = {
|
||||||
|
name: 'main',
|
||||||
|
isDefault: false,
|
||||||
|
isProtected: false,
|
||||||
|
branchProtection: {
|
||||||
|
allowForcePush: false,
|
||||||
|
codeOwnerApprovalRequired: false,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -27,11 +27,21 @@ RSpec.describe Groups::Settings::AccessTokensController do
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'GET /:namespace/-/settings/access_tokens' do
|
describe 'GET /:namespace/-/settings/access_tokens' do
|
||||||
subject do
|
let(:get_access_tokens) do
|
||||||
get group_settings_access_tokens_path(resource)
|
get group_settings_access_tokens_path(resource)
|
||||||
response
|
response
|
||||||
end
|
end
|
||||||
|
|
||||||
|
let(:get_access_tokens_json) do
|
||||||
|
get group_settings_access_tokens_path(resource), params: { format: :json }
|
||||||
|
response
|
||||||
|
end
|
||||||
|
|
||||||
|
subject(:get_access_tokens_with_page) do
|
||||||
|
get group_settings_access_tokens_path(resource), params: { page: 1 }
|
||||||
|
response
|
||||||
|
end
|
||||||
|
|
||||||
it_behaves_like 'feature unavailable'
|
it_behaves_like 'feature unavailable'
|
||||||
it_behaves_like 'GET resource access tokens available'
|
it_behaves_like 'GET resource access tokens available'
|
||||||
end
|
end
|
||||||
|
|
|
@ -28,11 +28,21 @@ RSpec.describe Projects::Settings::AccessTokensController do
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'GET /:namespace/:project/-/settings/access_tokens' do
|
describe 'GET /:namespace/:project/-/settings/access_tokens' do
|
||||||
subject do
|
let(:get_access_tokens) do
|
||||||
get project_settings_access_tokens_path(resource)
|
get project_settings_access_tokens_path(resource)
|
||||||
response
|
response
|
||||||
end
|
end
|
||||||
|
|
||||||
|
let(:get_access_tokens_json) do
|
||||||
|
get project_settings_access_tokens_path(resource), params: { format: :json }
|
||||||
|
response
|
||||||
|
end
|
||||||
|
|
||||||
|
subject(:get_access_tokens_with_page) do
|
||||||
|
get project_settings_access_tokens_path(resource), params: { page: 1 }
|
||||||
|
response
|
||||||
|
end
|
||||||
|
|
||||||
it_behaves_like 'feature unavailable'
|
it_behaves_like 'feature unavailable'
|
||||||
it_behaves_like 'GET resource access tokens available'
|
it_behaves_like 'GET resource access tokens available'
|
||||||
end
|
end
|
||||||
|
|
|
@ -113,8 +113,7 @@ RSpec.describe Glfm::UpdateSpecification, '#process' do
|
||||||
|
|
||||||
before do
|
before do
|
||||||
# Mock default ENV var values
|
# Mock default ENV var values
|
||||||
allow(ENV).to receive(:[]).with('UPDATE_GHFM_SPEC_MD').and_return(nil)
|
stub_env('UPDATE_GHFM_SPEC_MD')
|
||||||
allow(ENV).to receive(:[]).and_call_original
|
|
||||||
|
|
||||||
# We mock out the URI and local file IO objects with real StringIO, instead of just mock
|
# We mock out the URI and local file IO objects with real StringIO, instead of just mock
|
||||||
# objects. This gives better and more realistic coverage, while still avoiding
|
# objects. This gives better and more realistic coverage, while still avoiding
|
||||||
|
@ -166,7 +165,7 @@ RSpec.describe Glfm::UpdateSpecification, '#process' do
|
||||||
let(:ghfm_spec_txt_local_io) { StringIO.new }
|
let(:ghfm_spec_txt_local_io) { StringIO.new }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
allow(ENV).to receive(:[]).with('UPDATE_GHFM_SPEC_MD').and_return('true')
|
stub_env('UPDATE_GHFM_SPEC_MD', 'true')
|
||||||
allow(File).to receive(:open).with(ghfm_spec_md_path, 'w') { ghfm_spec_txt_local_io }
|
allow(File).to receive(:open).with(ghfm_spec_md_path, 'w') { ghfm_spec_txt_local_io }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -2,15 +2,6 @@
|
||||||
|
|
||||||
module Database
|
module Database
|
||||||
module MultipleDatabases
|
module MultipleDatabases
|
||||||
def run_and_cleanup(example)
|
|
||||||
# Each example may call `migrate!`, so we must ensure we are migrated down every time
|
|
||||||
schema_migrate_down!
|
|
||||||
|
|
||||||
example.run
|
|
||||||
|
|
||||||
delete_from_all_tables!(except: deletion_except_tables)
|
|
||||||
end
|
|
||||||
|
|
||||||
def skip_if_multiple_databases_not_setup
|
def skip_if_multiple_databases_not_setup
|
||||||
skip 'Skipping because multiple databases not set up' unless Gitlab::Database.has_config?(:ci)
|
skip 'Skipping because multiple databases not set up' unless Gitlab::Database.has_config?(:ci)
|
||||||
end
|
end
|
||||||
|
@ -40,10 +31,15 @@ module Database
|
||||||
config_model: base_model
|
config_model: base_model
|
||||||
)
|
)
|
||||||
|
|
||||||
schema_migrate_up!
|
|
||||||
delete_from_all_tables!(except: deletion_except_tables)
|
delete_from_all_tables!(except: deletion_except_tables)
|
||||||
|
schema_migrate_up!
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# ActiveRecord::Base.clear_all_connections! disconnects and clears attribute methods
|
||||||
|
# Force a refresh to avoid schema failures.
|
||||||
|
reset_column_in_all_models
|
||||||
|
refresh_attribute_methods
|
||||||
end
|
end
|
||||||
|
|
||||||
# The usage of this method switches temporarily used `connection_handler`
|
# The usage of this method switches temporarily used `connection_handler`
|
||||||
|
@ -152,10 +148,10 @@ RSpec.configure do |config|
|
||||||
config_model: base_model
|
config_model: base_model
|
||||||
)
|
)
|
||||||
|
|
||||||
run_and_cleanup(example)
|
example.run
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
run_and_cleanup(example)
|
example.run
|
||||||
end
|
end
|
||||||
|
|
||||||
self.class.use_transactional_tests = true
|
self.class.use_transactional_tests = true
|
||||||
|
|
|
@ -22,4 +22,14 @@ RSpec.configure do |config|
|
||||||
|
|
||||||
self.class.use_transactional_tests = true
|
self.class.use_transactional_tests = true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
config.around(:each, :migration) do |example|
|
||||||
|
self.class.use_transactional_tests = false
|
||||||
|
|
||||||
|
example.run
|
||||||
|
|
||||||
|
delete_from_all_tables!(except: deletion_except_tables)
|
||||||
|
|
||||||
|
self.class.use_transactional_tests = true
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -19,6 +19,8 @@ RSpec.configure do |config|
|
||||||
# Each example may call `migrate!`, so we must ensure we are migrated down every time
|
# Each example may call `migrate!`, so we must ensure we are migrated down every time
|
||||||
config.before(:each, :migration) do
|
config.before(:each, :migration) do
|
||||||
use_fake_application_settings
|
use_fake_application_settings
|
||||||
|
|
||||||
|
schema_migrate_down!
|
||||||
end
|
end
|
||||||
|
|
||||||
config.after(:context, :migration) do
|
config.after(:context, :migration) do
|
||||||
|
|
|
@ -4,7 +4,7 @@ RSpec.shared_examples 'GET resource access tokens available' do
|
||||||
let_it_be(:active_resource_access_token) { create(:personal_access_token, user: bot_user) }
|
let_it_be(:active_resource_access_token) { create(:personal_access_token, user: bot_user) }
|
||||||
|
|
||||||
it 'retrieves active resource access tokens' do
|
it 'retrieves active resource access tokens' do
|
||||||
subject
|
get_access_tokens
|
||||||
|
|
||||||
token_entities = assigns(:active_resource_access_tokens)
|
token_entities = assigns(:active_resource_access_tokens)
|
||||||
expect(token_entities.length).to eq(1)
|
expect(token_entities.length).to eq(1)
|
||||||
|
@ -12,10 +12,80 @@ RSpec.shared_examples 'GET resource access tokens available' do
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'lists all available scopes' do
|
it 'lists all available scopes' do
|
||||||
subject
|
get_access_tokens
|
||||||
|
|
||||||
expect(assigns(:scopes)).to eq(Gitlab::Auth.resource_bot_scopes)
|
expect(assigns(:scopes)).to eq(Gitlab::Auth.resource_bot_scopes)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'returns for json response' do
|
||||||
|
get_access_tokens_json
|
||||||
|
|
||||||
|
expect(json_response.count).to eq(1)
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when access_tokens are paginated" do
|
||||||
|
before do
|
||||||
|
allow(Kaminari.config).to receive(:default_per_page).and_return(1)
|
||||||
|
create(:personal_access_token, user: bot_user)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns paginated response", :aggregate_failures do
|
||||||
|
get_access_tokens_with_page
|
||||||
|
expect(assigns(:active_resource_access_tokens).count).to eq(1)
|
||||||
|
|
||||||
|
expect_header('X-Per-Page', '1')
|
||||||
|
expect_header('X-Page', '1')
|
||||||
|
expect_header('X-Next-Page', '2')
|
||||||
|
expect_header('X-Total', '2')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when access_token_pagination feature flag is disabled" do
|
||||||
|
before do
|
||||||
|
stub_feature_flags(access_token_pagination: false)
|
||||||
|
create(:personal_access_token, user: bot_user)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns all tokens in system" do
|
||||||
|
get_access_tokens_with_page
|
||||||
|
expect(assigns(:active_resource_access_tokens).count).to eq(2)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "as tokens returned are ordered" do
|
||||||
|
let(:expires_1_day_from_now) { 1.day.from_now.to_date }
|
||||||
|
let(:expires_2_day_from_now) { 2.days.from_now.to_date }
|
||||||
|
|
||||||
|
before do
|
||||||
|
create(:personal_access_token, user: bot_user, name: "Token1", expires_at: expires_1_day_from_now)
|
||||||
|
create(:personal_access_token, user: bot_user, name: "Token2", expires_at: expires_2_day_from_now)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "orders token list ascending on expires_at" do
|
||||||
|
get_access_tokens
|
||||||
|
|
||||||
|
first_token = assigns(:active_resource_access_tokens).first.as_json
|
||||||
|
expect(first_token['name']).to eq("Token1")
|
||||||
|
expect(first_token['expires_at']).to eq(expires_1_day_from_now.strftime("%Y-%m-%d"))
|
||||||
|
end
|
||||||
|
|
||||||
|
it "orders tokens on id in case token has same expires_at" do
|
||||||
|
create(:personal_access_token, user: bot_user, name: "Token3", expires_at: expires_1_day_from_now)
|
||||||
|
get_access_tokens
|
||||||
|
|
||||||
|
first_token = assigns(:active_resource_access_tokens).first.as_json
|
||||||
|
expect(first_token['name']).to eq("Token3")
|
||||||
|
expect(first_token['expires_at']).to eq(expires_1_day_from_now.strftime("%Y-%m-%d"))
|
||||||
|
|
||||||
|
second_token = assigns(:active_resource_access_tokens).second.as_json
|
||||||
|
expect(second_token['name']).to eq("Token1")
|
||||||
|
expect(second_token['expires_at']).to eq(expires_1_day_from_now.strftime("%Y-%m-%d"))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def expect_header(header_name, header_val)
|
||||||
|
expect(response.headers[header_name]).to eq(header_val)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
RSpec.shared_examples 'POST resource access tokens available' do
|
RSpec.shared_examples 'POST resource access tokens available' do
|
||||||
|
|
Loading…
Reference in a new issue