mirror of
https://github.com/gitlabhq/gitlabhq.git
synced 2025-07-23 00:45:28 +00:00
Add latest changes from gitlab-org/gitlab@16-4-stable-ee
This commit is contained in:
19
app/components/pajamas/broadcast_banner_component.html.haml
Normal file
19
app/components/pajamas/broadcast_banner_component.html.haml
Normal file
@ -0,0 +1,19 @@
|
||||
.gl-broadcast-message.broadcast-banner-message.banner{ role: 'alert',
|
||||
class: "js-broadcast-notification-#{@id} #{@theme}", data: { testid: 'banner-broadcast-message' } }
|
||||
.gl-broadcast-message-content
|
||||
.gl-broadcast-message-icon
|
||||
= sprite_icon('bullhorn')
|
||||
.gl-broadcast-message-text
|
||||
%h2.gl-sr-only= _('Admin message')
|
||||
= @message
|
||||
- if @dismissable
|
||||
= render Pajamas::ButtonComponent.new(category: :tertiary,
|
||||
icon: 'close',
|
||||
size: :small,
|
||||
button_options: { class: 'gl-close-btn-color-inherit gl-broadcast-message-dismiss js-dismiss-current-broadcast-notification',
|
||||
'aria-label': _('Close'),
|
||||
data: { id: @id,
|
||||
expire_date: @expire_date,
|
||||
dismissal_path: @dismissal_path,
|
||||
cookie_key: @cookie_key } },
|
||||
icon_classes: 'gl-text-white')
|
24
app/components/pajamas/broadcast_banner_component.rb
Normal file
24
app/components/pajamas/broadcast_banner_component.rb
Normal file
@ -0,0 +1,24 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Pajamas
|
||||
class BroadcastBannerComponent < Pajamas::Component
|
||||
# @param [String] message
|
||||
# @param [String] id
|
||||
# @param [String] theme
|
||||
# @param [Boolean] dismissable
|
||||
# @param [String] expire_date
|
||||
# @param [String] cookie_key
|
||||
# @param [String] dismissal_path
|
||||
def initialize(message:, id:, theme:, dismissable:, expire_date:, cookie_key:, dismissal_path: nil)
|
||||
@message = message
|
||||
@id = id
|
||||
@theme = theme
|
||||
@dismissable = dismissable
|
||||
@expire_date = expire_date
|
||||
@cookie_key = cookie_key
|
||||
@dismissal_path = dismissal_path
|
||||
end
|
||||
|
||||
delegate :sprite_icon, to: :helpers
|
||||
end
|
||||
end
|
@ -33,6 +33,10 @@ module AccessTokensHelper
|
||||
min_date: 1.day.from_now.iso8601
|
||||
}
|
||||
end
|
||||
|
||||
def show_token_expiration_banner?
|
||||
Gitlab::Auth::TokenExpirationBanner.show_token_expiration_banner?
|
||||
end
|
||||
end
|
||||
|
||||
AccessTokensHelper.prepend_mod
|
||||
|
@ -25,6 +25,7 @@
|
||||
= dispensable_render_if_exists "layouts/header/licensed_user_count_threshold"
|
||||
= dispensable_render_if_exists "layouts/header/token_expiry_notification"
|
||||
= dispensable_render "shared/projects/inactive_project_deletion_alert"
|
||||
= dispensable_render_if_exists "shared/token_expiration_banner"
|
||||
= dispensable_render "layouts/broadcast"
|
||||
= dispensable_render "layouts/header/read_only_banner"
|
||||
= dispensable_render "layouts/header/registration_enabled_callout"
|
||||
|
11
app/views/shared/_token_expiration_banner.html.haml
Normal file
11
app/views/shared/_token_expiration_banner.html.haml
Normal file
@ -0,0 +1,11 @@
|
||||
- id = 'token_expiration_banner'
|
||||
- cookie_key = 'hide_broadcast_message_token_expiration_banner'
|
||||
|
||||
- return unless show_token_expiration_banner?
|
||||
- return unless cookies[cookie_key].blank?
|
||||
|
||||
-# rubocop:disable Gitlab/DocUrl -- This documentation section is only available in version 17.1 onward.
|
||||
- link = link_to('', 'https://docs.gitlab.com/ee/security/token_overview.html#troubleshooting', target: '_blank', rel: 'noopener noreferrer')
|
||||
-# rubocop:enable Gitlab/DocUrl
|
||||
- message = safe_format(s_('AccessTokens|GitLab now enforces expiry dates on tokens that originally had no set expiration date. Those tokens were given an expiration date of one year later. Please review your personal access tokens, project access tokens, and group access tokens to ensure you are aware of upcoming expirations. Administrators of GitLab can find more information on how to identify and mitigate interruption in our %{link_start}documentation%{link_end}.'), tag_pair(link, :link_start, :link_end))
|
||||
= render Pajamas::BroadcastBannerComponent.new(message: message, id: id, theme: 'light-indigo', dismissable: true, expire_date: Time.now.next_year.iso8601, cookie_key: cookie_key)
|
@ -39,6 +39,7 @@ You can use the following environment variables to override certain values:
|
||||
| `RAILS_ENV` | string | The Rails environment; can be one of `production`, `development`, `staging`, or `test`. |
|
||||
| `GITLAB_RAILS_CACHE_DEFAULT_TTL_SECONDS` | integer | The default TTL used for entries stored in the Rails-cache. Default is `28800`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/95042) in 15.3. |
|
||||
| `GITLAB_CI_CONFIG_FETCH_TIMEOUT_SECONDS` | integer | Timeout for resolving remote includes in CI config in seconds. Must be between `0` and `60`. Default is `30`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/116383) in 15.11. |
|
||||
| `GITLAB_DISABLE_TOKEN_EXPIRATION_BANNER` | string | If set to `true`, `1`, or `yes`, the token expiration banner is not shown. Default is `false`. |
|
||||
|
||||
## Adding more variables
|
||||
|
||||
|
30
lib/gitlab/auth/token_expiration_banner.rb
Normal file
30
lib/gitlab/auth/token_expiration_banner.rb
Normal file
@ -0,0 +1,30 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Gitlab
|
||||
module Auth
|
||||
module TokenExpirationBanner
|
||||
module_function
|
||||
|
||||
# rubocop:disable Gitlab/ModuleWithInstanceVariables, CodeReuse/ActiveRecord -- simple query and should be memoized per app boot
|
||||
def show_token_expiration_banner?
|
||||
return @show_token_expiration_banner unless @show_token_expiration_banner.nil?
|
||||
|
||||
if %w[1 yes true].include?(ENV.fetch('GITLAB_DISABLE_TOKEN_EXPIRATION_BANNER', false))
|
||||
@show_token_expiration_banner = false
|
||||
return @show_token_expiration_banner
|
||||
end
|
||||
|
||||
unless Gitlab.version_info >= Gitlab::VersionInfo.new(16, 0) &&
|
||||
Gitlab.version_info < Gitlab::VersionInfo.new(17, 1)
|
||||
@show_token_expiration_banner = false
|
||||
return @show_token_expiration_banner
|
||||
end
|
||||
|
||||
@show_token_expiration_banner = Gitlab::Database::BackgroundMigration::BatchedMigration.where(
|
||||
job_class_name: 'CleanupPersonalAccessTokensWithNilExpiresAt'
|
||||
).exists?
|
||||
end
|
||||
# rubocop:enable Gitlab/ModuleWithInstanceVariables, CodeReuse/ActiveRecord
|
||||
end
|
||||
end
|
||||
end
|
@ -2526,6 +2526,9 @@ msgstr ""
|
||||
msgid "AccessTokens|For example, the application using the token or the purpose of the token. Do not give sensitive information for the name of the token, as it will be visible to all %{resource_type} members."
|
||||
msgstr ""
|
||||
|
||||
msgid "AccessTokens|GitLab now enforces expiry dates on tokens that originally had no set expiration date. Those tokens were given an expiration date of one year later. Please review your personal access tokens, project access tokens, and group access tokens to ensure you are aware of upcoming expirations. Administrators of GitLab can find more information on how to identify and mitigate interruption in our %{link_start}documentation%{link_end}."
|
||||
msgstr ""
|
||||
|
||||
msgid "AccessTokens|Incoming email token"
|
||||
msgstr ""
|
||||
|
||||
|
63
spec/components/pajamas/broadcast_banner_component_spec.rb
Normal file
63
spec/components/pajamas/broadcast_banner_component_spec.rb
Normal file
@ -0,0 +1,63 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Pajamas::BroadcastBannerComponent, :aggregate_failures, type: :component, feature_category: :navigation do
|
||||
before do
|
||||
render_inline described_class.new(message: message,
|
||||
id: id,
|
||||
theme: theme,
|
||||
dismissable: dismissable,
|
||||
expire_date: expire_date,
|
||||
cookie_key: cookie_key,
|
||||
dismissal_path: dismissal_path
|
||||
)
|
||||
end
|
||||
|
||||
let(:message) { '_message_' }
|
||||
let(:id) { '_99_' }
|
||||
let(:theme) { '_theme_' }
|
||||
let(:dismissable) { true }
|
||||
let(:expire_date) { Time.now.iso8601 }
|
||||
let(:cookie_key) { '_cookie_key_' }
|
||||
let(:dismissal_path) { '/-/my-path' }
|
||||
|
||||
it 'sets the correct classes' do
|
||||
expect(page).to have_selector(".js-broadcast-notification-#{id}")
|
||||
expect(page).to have_selector(".#{theme}")
|
||||
end
|
||||
|
||||
it 'contains a screen reader message' do
|
||||
expect(page).to have_selector('.gl-sr-only', text: _('Admin message'))
|
||||
end
|
||||
|
||||
it 'sets the message' do
|
||||
expect(page).to have_content(message)
|
||||
end
|
||||
|
||||
context 'when dismissable is true' do
|
||||
it 'display close button' do
|
||||
expect(page).to have_selector('button.js-dismiss-current-broadcast-notification')
|
||||
expect(page).to have_selector("button[data-id='#{id}']")
|
||||
expect(page).to have_selector("button[data-expire-date='#{expire_date}']")
|
||||
expect(page).to have_selector("button[data-dismissal-path='#{dismissal_path}']")
|
||||
expect(page).to have_selector("button[data-cookie-key='#{cookie_key}']")
|
||||
end
|
||||
|
||||
context 'when dismissal_path is no set' do
|
||||
let(:dismissal_path) { nil }
|
||||
|
||||
it 'display close button' do
|
||||
expect(page).not_to have_selector("button[data-dismissal-path='#{dismissal_path}']")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when dismissable is false' do
|
||||
let(:dismissable) { false }
|
||||
|
||||
it 'does not display close button' do
|
||||
expect(page).not_to have_selector('button.js-dismiss-current-broadcast-notification')
|
||||
end
|
||||
end
|
||||
end
|
@ -0,0 +1,32 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Pajamas
|
||||
class BroadcastBannerComponentPreview < ViewComponent::Preview
|
||||
# @param message text
|
||||
# @param id text
|
||||
# @param theme text
|
||||
# @param dismissable toggle
|
||||
# @param expire_date text
|
||||
# @param cookie_key text
|
||||
# @param dismissal_path text
|
||||
def default(
|
||||
message: 'Message for the broadcast banner',
|
||||
id: '99',
|
||||
theme: 'light-indigo',
|
||||
dismissable: true,
|
||||
expire_date: Time.now.next_year.iso8601,
|
||||
cookie_key: 'my_cookie',
|
||||
dismissal_path: '/my-path'
|
||||
)
|
||||
render(Pajamas::BroadcastBannerComponent.new(
|
||||
message: message,
|
||||
id: id,
|
||||
theme: theme,
|
||||
dismissable: dismissable,
|
||||
expire_date: expire_date,
|
||||
cookie_key: cookie_key,
|
||||
dismissal_path: dismissal_path
|
||||
))
|
||||
end
|
||||
end
|
||||
end
|
@ -72,4 +72,12 @@ RSpec.describe AccessTokensHelper do
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
describe '#show_token_expiration_banner?' do
|
||||
it 'calls the singleton method from the module' do
|
||||
expect(Gitlab::Auth::TokenExpirationBanner).to receive(:show_token_expiration_banner?)
|
||||
|
||||
helper.show_token_expiration_banner?
|
||||
end
|
||||
end
|
||||
end
|
||||
|
62
spec/lib/gitlab/auth/token_expiration_banner_spec.rb
Normal file
62
spec/lib/gitlab/auth/token_expiration_banner_spec.rb
Normal file
@ -0,0 +1,62 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Gitlab::Auth::TokenExpirationBanner, feature_category: :system_access do
|
||||
describe '.show_token_expiration_banner?' do
|
||||
subject(:show_token_expiration_banner) { described_class.show_token_expiration_banner? }
|
||||
|
||||
let(:gitlab_version) { Gitlab::VersionInfo.new(16, 0) }
|
||||
let(:model_class) { Gitlab::Database::BackgroundMigration::BatchedMigration }
|
||||
|
||||
# this method is meant to be memoized on app boot and not changed
|
||||
# for specs, we need to reset it each time
|
||||
before do
|
||||
described_class.instance_variable_set(:@show_token_expiration_banner, nil)
|
||||
allow(Gitlab).to receive(:version_info).twice.and_return(gitlab_version)
|
||||
end
|
||||
|
||||
it { is_expected.to be(false) }
|
||||
|
||||
it 'memoizes results' do
|
||||
expect(described_class.show_token_expiration_banner?).to be(false)
|
||||
expect(model_class).not_to receive(:where)
|
||||
|
||||
# Second call shouldn't trigger database query
|
||||
expect(show_token_expiration_banner).to be(false)
|
||||
end
|
||||
|
||||
context 'when the batched migration is present in the db' do
|
||||
before do
|
||||
create(
|
||||
:batched_background_migration,
|
||||
job_class_name: 'CleanupPersonalAccessTokensWithNilExpiresAt'
|
||||
)
|
||||
end
|
||||
|
||||
it { is_expected.to be(true) }
|
||||
|
||||
it 'memoizes results' do
|
||||
expect(described_class.show_token_expiration_banner?).to be(true)
|
||||
expect(model_class).not_to receive(:where)
|
||||
|
||||
# Second call shouldn't trigger database query
|
||||
expect(show_token_expiration_banner).to be(true)
|
||||
end
|
||||
|
||||
context 'when banner is disabled by env var' do
|
||||
before do
|
||||
stub_env('GITLAB_DISABLE_TOKEN_EXPIRATION_BANNER', '1')
|
||||
end
|
||||
|
||||
it { is_expected.to be(false) }
|
||||
end
|
||||
|
||||
context 'when not in affected version range' do
|
||||
let(:gitlab_version) { Gitlab::VersionInfo.new(17, 2) }
|
||||
|
||||
it { is_expected.to be(false) }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
18
spec/views/shared/_token_expiration_banner.html.haml_spec.rb
Normal file
18
spec/views/shared/_token_expiration_banner.html.haml_spec.rb
Normal file
@ -0,0 +1,18 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe 'shared/_token_expiration_banner.html.haml', feature_category: :system_access do
|
||||
context 'when all conditions are true' do
|
||||
before do
|
||||
allow(view).to receive(:show_token_expiration_banner?).and_return(true)
|
||||
allow(view).to receive(:cookies).and_return({ 'hide_broadcast_message_token_expiration_banner' => nil })
|
||||
end
|
||||
|
||||
it 'renders banner' do
|
||||
render 'shared/token_expiration_banner'
|
||||
|
||||
expect(rendered).to have_content 'GitLab now enforces expiry dates on tokens'
|
||||
end
|
||||
end
|
||||
end
|
Reference in New Issue
Block a user