Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2022-09-03 03:10:23 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2022-09-03 03:10:23 +0300
commit3bbc597f60f05baae319cc541564bf41639fd14e (patch)
tree3454a662854d115ad6f5a5ffc1afb21bc4fde008
parent36e64e679dfc3e5989445f06aa238962df6ca98d (diff)
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--app/assets/javascripts/access_tokens/components/access_token_table_app.vue1
-rw-r--r--app/finders/environments/environments_finder.rb7
-rw-r--r--app/models/environment.rb1
-rw-r--r--app/models/personal_access_token.rb1
-rw-r--r--doc/administration/operations/rails_console.md31
-rw-r--r--doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md31
-rw-r--r--doc/user/application_security/get-started-security.md24
-rw-r--r--lib/gitlab/cleanup/personal_access_tokens.rb (renamed from lib/gitlab/cleanup/unused_personal_access_tokens.rb)62
-rw-r--r--locale/gitlab.pot3
-rw-r--r--spec/finders/environments/environments_finder_spec.rb10
-rw-r--r--spec/frontend/access_tokens/components/access_token_table_app_spec.js15
-rw-r--r--spec/lib/error_tracking/sentry_client/issue_spec.rb4
-rw-r--r--spec/lib/error_tracking/sentry_client/projects_spec.rb4
-rw-r--r--spec/lib/gitlab/cleanup/personal_access_tokens_spec.rb (renamed from spec/lib/gitlab/cleanup/unused_personal_access_tokens_spec.rb)53
-rw-r--r--spec/models/environment_spec.rb10
-rw-r--r--spec/models/personal_access_token_spec.rb40
16 files changed, 207 insertions, 90 deletions
diff --git a/app/assets/javascripts/access_tokens/components/access_token_table_app.vue b/app/assets/javascripts/access_tokens/components/access_token_table_app.vue
index 59f0e0dd17d..461b2dad479 100644
--- a/app/assets/javascripts/access_tokens/components/access_token_table_app.vue
+++ b/app/assets/javascripts/access_tokens/components/access_token_table_app.vue
@@ -140,6 +140,7 @@ export default {
<template #cell(action)="{ item: { revokePath } }">
<gl-button
+ v-if="revokePath"
category="tertiary"
:aria-label="$options.i18n.revokeButton"
:data-confirm="modalMessage"
diff --git a/app/finders/environments/environments_finder.rb b/app/finders/environments/environments_finder.rb
index 46c49f096c6..f2dcba04349 100644
--- a/app/finders/environments/environments_finder.rb
+++ b/app/finders/environments/environments_finder.rb
@@ -14,6 +14,7 @@ module Environments
def execute
environments = project.environments
+ environments = by_type(environments)
environments = by_name(environments)
environments = by_search(environments)
environments = by_ids(environments)
@@ -24,6 +25,12 @@ module Environments
private
+ def by_type(environments)
+ return environments unless params[:type].present?
+
+ environments.for_type(params[:type])
+ end
+
def by_name(environments)
if params[:name].present?
environments.for_name(params[:name])
diff --git a/app/models/environment.rb b/app/models/environment.rb
index 1950431446b..bc1b2daf3db 100644
--- a/app/models/environment.rb
+++ b/app/models/environment.rb
@@ -89,6 +89,7 @@ class Environment < ApplicationRecord
scope :for_project, -> (project) { where(project_id: project) }
scope :for_tier, -> (tier) { where(tier: tier).where.not(tier: nil) }
+ scope :for_type, -> (type) { where(environment_type: type) }
scope :unfoldered, -> { where(environment_type: nil) }
scope :with_rank, -> do
select('environments.*, rank() OVER (PARTITION BY project_id ORDER BY id DESC)')
diff --git a/app/models/personal_access_token.rb b/app/models/personal_access_token.rb
index 8fc93e6f954..ed996589489 100644
--- a/app/models/personal_access_token.rb
+++ b/app/models/personal_access_token.rb
@@ -24,6 +24,7 @@ class PersonalAccessToken < ApplicationRecord
scope :expiring_and_not_notified, ->(date) { where(["revoked = false AND expire_notification_delivered = false AND expires_at >= CURRENT_DATE AND expires_at <= ?", date]) }
scope :expired_today_and_not_notified, -> { where(["revoked = false AND expires_at = CURRENT_DATE AND after_expiry_notification_delivered = false"]) }
scope :inactive, -> { where("revoked = true OR expires_at < CURRENT_DATE") }
+ scope :created_before, -> (date) { where("personal_access_tokens.created_at < :date", date: date) }
scope :last_used_before, -> (date) { where("personal_access_tokens.created_at < :date AND (last_used_at < :date OR last_used_at IS NULL)", date: date) }
scope :with_impersonation, -> { where(impersonation: true) }
scope :without_impersonation, -> { where(impersonation: false) }
diff --git a/doc/administration/operations/rails_console.md b/doc/administration/operations/rails_console.md
index 235f34e8de5..627dfbeb66c 100644
--- a/doc/administration/operations/rails_console.md
+++ b/doc/administration/operations/rails_console.md
@@ -218,6 +218,28 @@ instance_of_object.method(:foo).source_location
project.method(:private?).source_location
```
+## Limiting output
+
+Adding a semicolon(`;`) and a follow-up statement at the end of a statement prevents the default implicit return output. This can be used if you are already explicitly printing details and potentially have a lot of return output:
+
+```ruby
+puts ActiveRecord::Base.descendants; :ok
+Project.select(&:pages_deployed?).each {|p| puts p.pages_url }; true
+```
+
+## Get or store the result of last operation
+
+Underscore(`_`) represents the implicit return of the previous statement. You can use this to quickly assign a variable from the output of the previous command:
+
+```ruby
+Project.last
+# => #<Project id:2537 root/discard>>
+project = _
+# => #<Project id:2537 root/discard>>
+project.id
+# => 2537
+```
+
## Active Record objects
### Looking up database-persisted objects
@@ -347,6 +369,15 @@ D, [2020-03-05T17:18:30.406047 #910] DEBUG -- : User Load (2.6ms) SELECT "use
For more on different ways to retrieve data from the database using Active
Record, please see the [Active Record Query Interface documentation](https://guides.rubyonrails.org/active_record_querying.html).
+## Query the database using an Active Record model
+
+```ruby
+m = Model.where('attribute like ?', 'ex%')
+
+# for example to query the projects
+projects = Project.where('path like ?', 'Oumua%')
+```
+
### Modifying Active Record objects
In the previous section, we learned about retrieving database records using
diff --git a/doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md b/doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md
index 4f602ecf6e3..7d2b4a58955 100644
--- a/doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md
+++ b/doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md
@@ -62,28 +62,6 @@ Notify.test_email(e, "Test email for #{n}", 'Test email').deliver_now
Notify.test_email(u.email, "Test email for #{u.name}", 'Test email').deliver_now
```
-## Limiting output
-
-Adding a semicolon(`;`) and a follow-up statement at the end of a statement prevents the default implicit return output. This can be used if you are already explicitly printing details and potentially have a lot of return output:
-
-```ruby
-puts ActiveRecord::Base.descendants; :ok
-Project.select(&:pages_deployed?).each {|p| puts p.pages_url }; true
-```
-
-## Get or store the result of last operation
-
-Underscore(`_`) represents the implicit return of the previous statement. You can use this to quickly assign a variable from the output of the previous command:
-
-```ruby
-Project.last
-# => #<Project id:2537 root/discard>>
-project = _
-# => #<Project id:2537 root/discard>>
-project.id
-# => 2537
-```
-
## Open object in `irb`
Sometimes it is easier to go through a method if you are in the context of the object. You can shim into the namespace of `Object` to let you open `irb` in the context of any object:
@@ -99,15 +77,6 @@ irb(#<Project>)> web_url
# => "https://gitlab-example/root/discard"
```
-## Query the database using an ActiveRecord Model
-
-```ruby
-m = Model.where('attribute like ?', 'ex%')
-
-# for example to query the projects
-projects = Project.where('path like ?', 'Oumua%')
-```
-
## View all keys in cache
```ruby
diff --git a/doc/user/application_security/get-started-security.md b/doc/user/application_security/get-started-security.md
index 4c2b971b5fa..9d98675c2df 100644
--- a/doc/user/application_security/get-started-security.md
+++ b/doc/user/application_security/get-started-security.md
@@ -6,25 +6,33 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Get started with GitLab application security **(ULTIMATE)**
-Complete the following steps to get the most from GitLab application security tools.
+The following steps will help you get the most from GitLab application security tools. These steps are a recommended order of operations. You can choose to implement capabilities in a different order or omit features that do not apply to your specific needs.
-1. Enable [Secret Detection](secret_detection/index.md) scanning for your default branch.
-1. Enable [Dependency Scanning](dependency_scanning/index.md) for your default branch so you can start identifying existing
+1. Enable [Secret Detection](secret_detection/index.md) and [Dependency Scanning](dependency_scanning/index.md)
+ to identify any leaked secrets and vulnerable packages in your codebase.
+
+ - For all security scanners, enable them by updating your `[.gitlab-ci.yml](../../ci/yaml/gitlab_ci_yaml.md)` directly on your `default` branch. This creates a baseline scan of your `default` branch, which is necessary for
+ feature branch scans to be compared against. This allows [merge requests](../project/merge_requests/index.md)
+ to display only newly-introduced vulnerabilities. Otherwise, merge requests will display every
+ vulnerability in the branch, regardless of whether it was introduced by a change in the branch.
+ - If you are after simplicity, enable only Secret Detection first. It only has one analyzer,
+ no build requirements, and relatively simple findings: is this a secret or not?
+ - It is good practice to enable Dependency Scanning early so you can start identifying existing
vulnerable packages in your codebase.
-1. Add security scans to feature branch pipelines. The same scans should be enabled as are running
- on your default branch. Subsequent scans will show only new vulnerabilities by comparing the feature branch to the default branch results.
1. Let your team get comfortable with [vulnerability reports](vulnerability_report/index.md) and
establish a vulnerability triage workflow.
1. Consider creating [labels](../project/labels.md) and [issue boards](../project/issue_board.md) to
help manage issues created from vulnerabilities. Issue boards allow all stakeholders to have a
- common view of all issues.
+ common view of all issues and track remediation progress.
+1. Use [scheduled pipelines](../../ci/pipelines/schedules.md#scheduled-pipelines) to regularly scan important branches such as `default` or those used for maintenance releases.
+ - Running regular dependency and [container scans](container_scanning/index.md) will surface newly-discovered vulnerabilities that already exist in your repository.
+ - Scheduled scans are most useful for projects or important branches with low development activity where pipeline scans are infrequent.
1. Create a [scan result policy](policies/index.md) to limit new vulnerabilities from being merged
- into your default branch.
+ into your `default` branch.
1. Monitor the [Security Dashboard](security_dashboard/index.md) trends to gauge success in
remediating existing vulnerabilities and preventing the introduction of new ones.
1. Enable other scan types such as [SAST](sast/index.md), [DAST](dast/index.md),
[Fuzz testing](coverage_fuzzing/index.md), or [Container Scanning](container_scanning/index.md).
- Be sure to add the same scan types to both feature pipelines and default branch pipelines.
1. Use [Compliance Pipelines](../../user/project/settings/index.md#compliance-pipeline-configuration)
or [Scan Execution Policies](policies/scan-execution-policies.md) to enforce required scan types
and ensure separation of duties between security and engineering.
diff --git a/lib/gitlab/cleanup/unused_personal_access_tokens.rb b/lib/gitlab/cleanup/personal_access_tokens.rb
index 97bf808a0ca..88665e6ada5 100644
--- a/lib/gitlab/cleanup/unused_personal_access_tokens.rb
+++ b/lib/gitlab/cleanup/personal_access_tokens.rb
@@ -2,31 +2,23 @@
module Gitlab
module Cleanup
- # Unused active Personal Access Tokens pose a risk to organizations
- # in that they may have been, or may be, leaked to unauthorized
- # individuals. They are likely providing little / no current value
- # because they are not actively being used, and should therefore be
- # proactively revoked.
- class UnusedPersonalAccessTokens
- # By default tokens that haven't been used for over 1 year will
- # be revoked
+ class PersonalAccessTokens
+ # By default tokens that haven't been used for over 1 year will be revoked
DEFAULT_TIME_PERIOD = 1.year
- # To prevent inadvertently revoking actively used tokens, we
- # provide a minimum time
+ # To prevent inadvertently revoking all tokens, we provide a minimum time
MINIMUM_TIME_PERIOD = 1.day
- attr_reader :logger, :last_used_before, :revocation_time, :group
+ attr_reader :logger, :cut_off_date, :revocation_time, :group
- def initialize(last_used_before: DEFAULT_TIME_PERIOD.ago.beginning_of_day, logger: nil, group_full_path:)
- # binding.pry
- # Ensure last_used_before is a Time and far enough in the past
- @last_used_before = last_used_before
+ def initialize(cut_off_date: DEFAULT_TIME_PERIOD.ago.beginning_of_day, logger: nil, group_full_path:)
+ @cut_off_date = cut_off_date
# rubocop: disable CodeReuse/ActiveRecord
@group = Group.find_by_full_path(group_full_path)
# rubocop: enable CodeReuse/ActiveRecord
+
raise "Group with full_path #{group_full_path} not found" unless @group
- raise "Invalid time: #{@last_used_before}" unless @last_used_before <= MINIMUM_TIME_PERIOD.ago
+ raise "Invalid time: #{@cut_off_date}" unless @cut_off_date <= MINIMUM_TIME_PERIOD.ago
# Use a static revocation time to make correlation of revoked
# tokens easier, should it be needed.
@@ -36,27 +28,21 @@ module Gitlab
raise "Invalid logger: #{@logger}" unless @logger.respond_to?(:info) && @logger.respond_to?(:warn)
end
- # Revokes unused personal access tokens.
- # A dry run is performed by default, logging what would be
- # revoked. Pass `dry_run: false` explicitly to revoke tokens.
- def run!(dry_run: true)
+ def run!(dry_run: true, revoke_active_tokens: false)
# rubocop:disable Rails/Output
if dry_run
puts "Dry running. No changes will be made"
+ elsif revoke_active_tokens
+ puts "Revoking used and unused access tokens created before #{cut_off_date}..."
else
- puts "Revoking access tokens from before #{last_used_before}..."
+ puts "Revoking access tokens last used and created before #{cut_off_date}..."
end
# rubocop:enable Rails/Output
- logger.info(
- dry_run: dry_run,
- group_full_path: group.full_path,
- message: "Looking for Personal Access Tokens " \
- "last used before #{last_used_before}..."
- )
+ tokens_to_revoke = revocable_tokens(revoke_active_tokens)
# rubocop:disable Cop/InBatches
- revocable_tokens.in_batches do |access_tokens|
+ tokens_to_revoke.in_batches do |access_tokens|
revoke_batch(access_tokens, dry_run)
end
# rubocop:enable Cop/InBatches
@@ -64,12 +50,20 @@ module Gitlab
private
- def revocable_tokens
- PersonalAccessToken
- .active
- .owner_is_human
- .last_used_before(last_used_before)
- .for_users(group.users)
+ def revocable_tokens(revoke_active_tokens)
+ if revoke_active_tokens
+ PersonalAccessToken
+ .active
+ .owner_is_human
+ .created_before(cut_off_date)
+ .for_users(group.users)
+ else
+ PersonalAccessToken
+ .active
+ .owner_is_human
+ .last_used_before(cut_off_date)
+ .for_users(group.users)
+ end
end
def revoke_batch(access_tokens, dry_run)
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index d946108264e..bcfc87fa078 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -11576,6 +11576,9 @@ msgstr ""
msgid "CycleAnalytics|Average time to completion"
msgstr ""
+msgid "CycleAnalytics|Average time to completion (days)"
+msgstr ""
+
msgid "CycleAnalytics|Change Failure Rate"
msgstr ""
diff --git a/spec/finders/environments/environments_finder_spec.rb b/spec/finders/environments/environments_finder_spec.rb
index 71d10ceb5d3..04fbd4067b4 100644
--- a/spec/finders/environments/environments_finder_spec.rb
+++ b/spec/finders/environments/environments_finder_spec.rb
@@ -6,8 +6,8 @@ RSpec.describe Environments::EnvironmentsFinder do
let_it_be(:project) { create(:project, :repository) }
let_it_be(:user) { project.creator }
let_it_be(:environment) { create(:environment, :available, project: project) }
- let_it_be(:environment_stopped) { create(:environment, :stopped, name: 'test2', project: project) }
- let_it_be(:environment_available) { create(:environment, :available, name: 'test3', project: project) }
+ let_it_be(:environment_stopped) { create(:environment, :stopped, name: 'test/test2', project: project) }
+ let_it_be(:environment_available) { create(:environment, :available, name: 'test/test3', project: project) }
before do
project.add_maintainer(user)
@@ -65,5 +65,11 @@ RSpec.describe Environments::EnvironmentsFinder do
expect(result).to contain_exactly(environment_available)
end
end
+
+ it 'filters environments by type' do
+ result = described_class.new(project, user, type: 'test').execute
+
+ expect(result).to contain_exactly(environment_stopped, environment_available)
+ end
end
end
diff --git a/spec/frontend/access_tokens/components/access_token_table_app_spec.js b/spec/frontend/access_tokens/components/access_token_table_app_spec.js
index 6013fa3ec39..aed3db4aa4c 100644
--- a/spec/frontend/access_tokens/components/access_token_table_app_spec.js
+++ b/spec/frontend/access_tokens/components/access_token_table_app_spec.js
@@ -190,6 +190,21 @@ describe('~/access_tokens/components/access_token_table_app', () => {
expect(button.props('category')).toBe('tertiary');
});
+ describe('revoke path', () => {
+ beforeEach(() => {
+ createComponent({ showRole: true });
+ });
+
+ it.each([{ revoke_path: null }, { revoke_path: undefined }])(
+ 'with %p, does not show revoke button',
+ async (input) => {
+ await triggerSuccess(defaultActiveAccessTokens.map((data) => ({ ...data, ...input })));
+
+ expect(findCells().at(6).findComponent(GlButton).exists()).toBe(false);
+ },
+ );
+ });
+
it('sorts rows alphabetically', async () => {
createComponent({ showRole: true });
await triggerSuccess();
diff --git a/spec/lib/error_tracking/sentry_client/issue_spec.rb b/spec/lib/error_tracking/sentry_client/issue_spec.rb
index d7bb0ca5c9a..8c02557b57b 100644
--- a/spec/lib/error_tracking/sentry_client/issue_spec.rb
+++ b/spec/lib/error_tracking/sentry_client/issue_spec.rb
@@ -151,7 +151,7 @@ RSpec.describe ErrorTracking::SentryClient::Issue do
context 'with older sentry versions where keys are not present' do
let(:sentry_api_response) do
- issues_sample_response[0...1].map do |issue|
+ issues_sample_response.first(1).map do |issue|
issue[:project].delete(:id)
issue
end
@@ -167,7 +167,7 @@ RSpec.describe ErrorTracking::SentryClient::Issue do
context 'when essential keys are missing in API response' do
let(:sentry_api_response) do
- issues_sample_response[0...1].map do |issue|
+ issues_sample_response.first(1).map do |issue|
issue.except(:id)
end
end
diff --git a/spec/lib/error_tracking/sentry_client/projects_spec.rb b/spec/lib/error_tracking/sentry_client/projects_spec.rb
index 247f9c1c085..81b44d0f6b1 100644
--- a/spec/lib/error_tracking/sentry_client/projects_spec.rb
+++ b/spec/lib/error_tracking/sentry_client/projects_spec.rb
@@ -38,7 +38,7 @@ RSpec.describe ErrorTracking::SentryClient::Projects do
context 'essential keys missing in API response' do
let(:sentry_api_response) do
- projects_sample_response[0...1].map do |project|
+ projects_sample_response.first(1).map do |project|
project.except(:slug)
end
end
@@ -50,7 +50,7 @@ RSpec.describe ErrorTracking::SentryClient::Projects do
context 'optional keys missing in sentry response' do
let(:sentry_api_response) do
- projects_sample_response[0...1].map do |project|
+ projects_sample_response.first(1).map do |project|
project[:organization].delete(:id)
project.delete(:id)
project.except(:status)
diff --git a/spec/lib/gitlab/cleanup/unused_personal_access_tokens_spec.rb b/spec/lib/gitlab/cleanup/personal_access_tokens_spec.rb
index eb83ced0e21..36c5d0e9b0c 100644
--- a/spec/lib/gitlab/cleanup/unused_personal_access_tokens_spec.rb
+++ b/spec/lib/gitlab/cleanup/personal_access_tokens_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Gitlab::Cleanup::UnusedPersonalAccessTokens do
+RSpec.describe Gitlab::Cleanup::PersonalAccessTokens do
let_it_be(:group) { create(:group) }
let_it_be(:subgroup) { create(:group, parent: group) }
let_it_be(:project_bot) { create(:user, :project_bot) }
@@ -16,6 +16,10 @@ RSpec.describe Gitlab::Cleanup::UnusedPersonalAccessTokens do
create(:personal_access_token, created_at: last_used_at - 1.minute)
end
+ let!(:old_actively_used_token) do
+ create(:personal_access_token, created_at: last_used_at - 1.minute, last_used_at: 1.day.ago)
+ end
+
let!(:old_unused_token_for_non_group_member) do
create(:personal_access_token, created_at: last_used_at - 1.minute)
end
@@ -37,6 +41,7 @@ RSpec.describe Gitlab::Cleanup::UnusedPersonalAccessTokens do
before do
group.add_member(old_formerly_used_token.user, Gitlab::Access::DEVELOPER)
+ group.add_member(old_actively_used_token.user, Gitlab::Access::DEVELOPER)
group.add_member(unused_token.user, Gitlab::Access::DEVELOPER)
group.add_member(old_unused_token.user, Gitlab::Access::DEVELOPER)
group.add_member(project_bot, Gitlab::Access::MAINTAINER)
@@ -47,7 +52,7 @@ RSpec.describe Gitlab::Cleanup::UnusedPersonalAccessTokens do
subject do
described_class.new(
logger: logger,
- last_used_before: last_used_at,
+ cut_off_date: last_used_at,
group_full_path: group_full_path
)
end
@@ -76,16 +81,42 @@ RSpec.describe Gitlab::Cleanup::UnusedPersonalAccessTokens do
context 'in a real run' do
let(:args) { { dry_run: false } }
- it 'revokes only revocable tokens' do
- subject.run!(**args)
+ context 'when revoking unused tokens' do
+ it 'revokes human-owned tokens created and last used over 1 year ago' do
+ subject.run!(**args)
+
+ expect(PersonalAccessToken.active).to contain_exactly(
+ unused_token,
+ old_actively_used_token,
+ old_unused_project_access_token,
+ old_unused_token_for_non_group_member,
+ old_unused_token_for_subgroup_member
+ )
+ expect(PersonalAccessToken.revoked).to contain_exactly(
+ old_unused_token,
+ old_formerly_used_token
+ )
+ end
+ end
+
+ context 'when revoking used and unused tokens' do
+ let(:args) { { dry_run: false, revoke_active_tokens: true } }
+
+ it 'revokes human-owned tokens created over 1 year ago' do
+ subject.run!(**args)
- expect(PersonalAccessToken.active).to contain_exactly(
- unused_token,
- old_unused_project_access_token,
- old_unused_token_for_non_group_member,
- old_unused_token_for_subgroup_member
- )
- expect(PersonalAccessToken.revoked).to contain_exactly(old_unused_token, old_formerly_used_token)
+ expect(PersonalAccessToken.active).to contain_exactly(
+ unused_token,
+ old_unused_project_access_token,
+ old_unused_token_for_non_group_member,
+ old_unused_token_for_subgroup_member
+ )
+ expect(PersonalAccessToken.revoked).to contain_exactly(
+ old_unused_token,
+ old_actively_used_token,
+ old_formerly_used_token
+ )
+ end
end
it 'updates updated_at' do
diff --git a/spec/models/environment_spec.rb b/spec/models/environment_spec.rb
index 3f4372dafd0..12b0691420e 100644
--- a/spec/models/environment_spec.rb
+++ b/spec/models/environment_spec.rb
@@ -318,6 +318,16 @@ RSpec.describe Environment, :use_clean_rails_memory_store_caching do
end
end
+ describe '.for_type' do
+ it 'filters by type' do
+ create(:environment)
+ create(:environment, name: 'type1/prod')
+ env = create(:environment, name: 'type2/prod')
+
+ expect(described_class.for_type('type2')).to contain_exactly(env)
+ end
+ end
+
describe '#guess_tier' do
using RSpec::Parameterized::TableSyntax
diff --git a/spec/models/personal_access_token_spec.rb b/spec/models/personal_access_token_spec.rb
index 9a2a35c0839..68230e81c50 100644
--- a/spec/models/personal_access_token_spec.rb
+++ b/spec/models/personal_access_token_spec.rb
@@ -65,6 +65,46 @@ RSpec.describe PersonalAccessToken do
end
end
+ describe '.created_before' do
+ let(:last_used_at) { 1.month.ago.beginning_of_hour }
+ let!(:new_used_token) do
+ create(:personal_access_token,
+ created_at: last_used_at + 1.minute,
+ last_used_at: last_used_at + 1.minute
+ )
+ end
+
+ let!(:old_unused_token) do
+ create(:personal_access_token,
+ created_at: last_used_at - 1.minute
+ )
+ end
+
+ let!(:old_formerly_used_token) do
+ create(:personal_access_token,
+ created_at: last_used_at - 1.minute,
+ last_used_at: last_used_at - 1.minute
+ )
+ end
+
+ let!(:old_still_used_token) do
+ create(:personal_access_token,
+ created_at: last_used_at - 1.minute,
+ last_used_at: 1.minute.ago
+ )
+ end
+
+ subject { described_class.created_before(last_used_at) }
+
+ it do
+ is_expected.to contain_exactly(
+ old_unused_token,
+ old_formerly_used_token,
+ old_still_used_token
+ )
+ end
+ end
+
describe '.last_used_before' do
let(:last_used_at) { 1.month.ago.beginning_of_hour }
let!(:unused_token) { create(:personal_access_token) }