From 4bf395cded929b1f2d2419079d8107604c9f930f Mon Sep 17 00:00:00 2001 From: GitLab Bot Date: Tue, 3 Aug 2021 21:09:39 +0000 Subject: Add latest changes from gitlab-org/gitlab@master --- .../behaviors/markdown/render_mermaid.js | 1 + app/assets/stylesheets/components/whats_new.scss | 2 +- .../admin/impersonation_tokens_controller.rb | 5 +++ app/controllers/dashboard/todos_controller.rb | 2 ++ app/controllers/invites_controller.rb | 4 +-- app/controllers/projects/pipelines_controller.rb | 4 +-- .../project_pipeline_statistics_resolver.rb | 4 +++ app/graphql/resolvers/todo_resolver.rb | 2 +- app/graphql/types/alert_management/alert_type.rb | 8 ++--- app/graphql/types/project_type.rb | 2 +- app/graphql/types/user_interface.rb | 7 ++-- app/models/alert_management/alert.rb | 4 +++ app/models/application_record.rb | 8 +++++ app/models/commit.rb | 4 +++ .../concerns/project_features_compatibility.rb | 4 --- app/models/design_management/design.rb | 4 --- app/models/group.rb | 4 --- app/models/issue.rb | 38 ++++++++++---------- app/models/note.rb | 10 ------ app/models/project.rb | 6 ++-- app/policies/issue_policy.rb | 13 ++++++- app/policies/personal_access_token_policy.rb | 2 +- app/policies/project_policy.rb | 4 +++ app/policies/todo_policy.rb | 7 ++-- app/services/issues/base_service.rb | 3 ++ .../todos/allowed_target_filter_service.rb | 18 ++++++++++ app/views/admin/users/_head.html.haml | 5 +-- app/views/dashboard/todos/index.html.haml | 8 ++--- app/views/invites/show.html.haml | 41 +++++++++++----------- app/views/projects/empty.html.haml | 8 ++--- .../shared/_check_recovery_settings.html.haml | 14 +++++--- 31 files changed, 147 insertions(+), 99 deletions(-) create mode 100644 app/services/todos/allowed_target_filter_service.rb (limited to 'app') diff --git a/app/assets/javascripts/behaviors/markdown/render_mermaid.js b/app/assets/javascripts/behaviors/markdown/render_mermaid.js index 293fe9f4133..3f878949f9b 100644 --- a/app/assets/javascripts/behaviors/markdown/render_mermaid.js +++ b/app/assets/javascripts/behaviors/markdown/render_mermaid.js @@ -66,6 +66,7 @@ export function initMermaid(mermaid) { useMaxWidth: true, htmlLabels: true, }, + secure: ['secure', 'securityLevel', 'startOnLoad', 'maxTextSize', 'htmlLabels'], securityLevel: 'strict', }); diff --git a/app/assets/stylesheets/components/whats_new.scss b/app/assets/stylesheets/components/whats_new.scss index 87593f53136..4437b5b673d 100644 --- a/app/assets/stylesheets/components/whats_new.scss +++ b/app/assets/stylesheets/components/whats_new.scss @@ -36,7 +36,7 @@ } .with-performance-bar .whats-new-drawer { - margin-top: calc(#{$performance-bar-height} + #{$header-height}); + margin-top: $performance-bar-height + $header-height; } .with-system-header .whats-new-drawer { diff --git a/app/controllers/admin/impersonation_tokens_controller.rb b/app/controllers/admin/impersonation_tokens_controller.rb index c3166d5dd82..eb279298baf 100644 --- a/app/controllers/admin/impersonation_tokens_controller.rb +++ b/app/controllers/admin/impersonation_tokens_controller.rb @@ -2,6 +2,7 @@ class Admin::ImpersonationTokensController < Admin::ApplicationController before_action :user + before_action :verify_impersonation_enabled! feature_category :authentication_and_authorization @@ -41,6 +42,10 @@ class Admin::ImpersonationTokensController < Admin::ApplicationController end # rubocop: enable CodeReuse/ActiveRecord + def verify_impersonation_enabled! + access_denied! unless helpers.impersonation_enabled? + end + def finder(options = {}) PersonalAccessTokensFinder.new({ user: user, impersonation: true }.merge(options)) end diff --git a/app/controllers/dashboard/todos_controller.rb b/app/controllers/dashboard/todos_controller.rb index 25ac0af9731..21bbb4d0c98 100644 --- a/app/controllers/dashboard/todos_controller.rb +++ b/app/controllers/dashboard/todos_controller.rb @@ -16,6 +16,8 @@ class Dashboard::TodosController < Dashboard::ApplicationController @todos = @todos.with_entity_associations return if redirect_out_of_range(@todos, todos_page_count(@todos)) + + @allowed_todos = ::Todos::AllowedTargetFilterService.new(@todos, current_user).execute end def destroy diff --git a/app/controllers/invites_controller.rb b/app/controllers/invites_controller.rb index 9a674d02b3f..e2b7f691e01 100644 --- a/app/controllers/invites_controller.rb +++ b/app/controllers/invites_controller.rb @@ -20,7 +20,7 @@ class InvitesController < ApplicationController end def accept - if member.accept_invite!(current_user) + if current_user_matches_invite? && member.accept_invite!(current_user) redirect_to invite_details[:path], notice: helpers.invite_accepted_notice(member) else redirect_back_or_default(options: { alert: _("The invitation could not be accepted.") }) @@ -52,7 +52,7 @@ class InvitesController < ApplicationController end def current_user_matches_invite? - @member.invite_email == current_user.email + current_user.verified_emails.include?(@member.invite_email) end def member? diff --git a/app/controllers/projects/pipelines_controller.rb b/app/controllers/projects/pipelines_controller.rb index ce93ac285a8..bad81bb36f0 100644 --- a/app/controllers/projects/pipelines_controller.rb +++ b/app/controllers/projects/pipelines_controller.rb @@ -8,8 +8,8 @@ class Projects::PipelinesController < Projects::ApplicationController before_action :pipeline, except: [:index, :new, :create, :charts, :config_variables] before_action :set_pipeline_path, only: [:show] before_action :authorize_read_pipeline! - before_action :authorize_read_build!, only: [:index] - before_action :authorize_read_analytics!, only: [:charts] + before_action :authorize_read_build!, only: [:index, :show] + before_action :authorize_read_ci_cd_analytics!, only: [:charts] before_action :authorize_create_pipeline!, only: [:new, :create, :config_variables] before_action :authorize_update_pipeline!, only: [:retry, :cancel] before_action do diff --git a/app/graphql/resolvers/project_pipeline_statistics_resolver.rb b/app/graphql/resolvers/project_pipeline_statistics_resolver.rb index 29ab9402f5b..79d01b9bf2e 100644 --- a/app/graphql/resolvers/project_pipeline_statistics_resolver.rb +++ b/app/graphql/resolvers/project_pipeline_statistics_resolver.rb @@ -2,8 +2,12 @@ module Resolvers class ProjectPipelineStatisticsResolver < BaseResolver + include Gitlab::Graphql::Authorize::AuthorizeResource type Types::Ci::AnalyticsType, null: true + authorizes_object! + authorize :read_ci_cd_analytics + def resolve weekly_stats = Gitlab::Ci::Charts::WeekChart.new(object) monthly_stats = Gitlab::Ci::Charts::MonthChart.new(object) diff --git a/app/graphql/resolvers/todo_resolver.rb b/app/graphql/resolvers/todo_resolver.rb index 9de61e95898..263b190c74e 100644 --- a/app/graphql/resolvers/todo_resolver.rb +++ b/app/graphql/resolvers/todo_resolver.rb @@ -34,7 +34,7 @@ module Resolvers return Todo.none unless current_user.present? && target.present? return Todo.none if target.is_a?(User) && target != current_user - TodosFinder.new(current_user, todo_finder_params(args)).execute + TodosFinder.new(current_user, todo_finder_params(args)).execute.with_entity_associations end private diff --git a/app/graphql/types/alert_management/alert_type.rb b/app/graphql/types/alert_management/alert_type.rb index b8fefaee470..bdfdd2c5886 100644 --- a/app/graphql/types/alert_management/alert_type.rb +++ b/app/graphql/types/alert_management/alert_type.rb @@ -115,11 +115,9 @@ module Types null: true, description: 'Runbook for the alert as defined in alert details.' - field :todos, - Types::TodoType.connection_type, - null: true, - description: 'To-do items of the current user for the alert.', - resolver: Resolvers::TodoResolver + field :todos, description: 'To-do items of the current user for the alert.', resolver: Resolvers::TodoResolver do + extension(::Gitlab::Graphql::TodosProjectPermissionPreloader::FieldExtension) + end field :details_url, GraphQL::Types::String, diff --git a/app/graphql/types/project_type.rb b/app/graphql/types/project_type.rb index 62861fceb1a..7a0f5ef9584 100644 --- a/app/graphql/types/project_type.rb +++ b/app/graphql/types/project_type.rb @@ -82,7 +82,7 @@ module Types snippets: 'Snippets are', container_registry: 'Container Registry is' }.each do |feature, name_string| - field "#{feature}_enabled", GraphQL::BOOLEAN_TYPE, null: true, + field "#{feature}_enabled", GraphQL::Types::Boolean, null: true, description: "Indicates if #{name_string} enabled for the current user" define_method "#{feature}_enabled" do diff --git a/app/graphql/types/user_interface.rb b/app/graphql/types/user_interface.rb index 045f612691b..d77ecd8b19d 100644 --- a/app/graphql/types/user_interface.rb +++ b/app/graphql/types/user_interface.rb @@ -55,9 +55,6 @@ module Types type: GraphQL::Types::String, null: false, description: 'Web path of the user.' - field :todos, - resolver: Resolvers::TodoResolver, - description: 'To-do items of the user.' field :group_memberships, type: Types::GroupMemberType.connection_type, null: true, @@ -81,6 +78,10 @@ module Types description: 'Projects starred by the user.', resolver: Resolvers::UserStarredProjectsResolver + field :todos, resolver: Resolvers::TodoResolver, description: 'To-do items of the user.' do + extension(::Gitlab::Graphql::TodosProjectPermissionPreloader::FieldExtension) + end + # Merge request field: MRs can be authored, assigned, or assigned-for-review: field :authored_merge_requests, resolver: Resolvers::AuthoredMergeRequestsResolver, diff --git a/app/models/alert_management/alert.rb b/app/models/alert_management/alert.rb index 679406e68d7..d0e4163dcdb 100644 --- a/app/models/alert_management/alert.rb +++ b/app/models/alert_management/alert.rb @@ -266,6 +266,10 @@ module AlertManagement end end + def to_ability_name + 'alert_management_alert' + end + private def hook_data diff --git a/app/models/application_record.rb b/app/models/application_record.rb index 3ad25a7e555..d362cfac4be 100644 --- a/app/models/application_record.rb +++ b/app/models/application_record.rb @@ -103,4 +103,12 @@ class ApplicationRecord < ActiveRecord::Base def self.cached_column_list self.column_names.map { |column_name| self.arel_table[column_name] } end + + def readable_by?(user) + Ability.allowed?(user, "read_#{to_ability_name}".to_sym, self) + end + + def to_ability_name + model_name.element + end end diff --git a/app/models/commit.rb b/app/models/commit.rb index a1ed5eb9ab9..8e7f526c512 100644 --- a/app/models/commit.rb +++ b/app/models/commit.rb @@ -550,6 +550,10 @@ class Commit expire_note_etag_cache_for_related_mrs end + def readable_by?(user) + Ability.allowed?(user, :read_commit, self) + end + private def expire_note_etag_cache_for_related_mrs diff --git a/app/models/concerns/project_features_compatibility.rb b/app/models/concerns/project_features_compatibility.rb index 121b696a659..0cab874a240 100644 --- a/app/models/concerns/project_features_compatibility.rb +++ b/app/models/concerns/project_features_compatibility.rb @@ -95,10 +95,6 @@ module ProjectFeaturesCompatibility # attribute. def container_registry_enabled=(value) write_feature_attribute_boolean(:container_registry_access_level, value) - - # TODO: Remove this when we remove the projects.container_registry_enabled - # column. https://gitlab.com/gitlab-org/gitlab/-/issues/335425 - super end private diff --git a/app/models/design_management/design.rb b/app/models/design_management/design.rb index e2d10cc7e78..79f5a63bcb6 100644 --- a/app/models/design_management/design.rb +++ b/app/models/design_management/design.rb @@ -182,10 +182,6 @@ module DesignManagement File.join(DesignManagement.designs_directory, "issue-#{issue.iid}", design.filename) end - def to_ability_name - 'design' - end - def description '' end diff --git a/app/models/group.rb b/app/models/group.rb index f1c1ed90459..1dda87eb48a 100644 --- a/app/models/group.rb +++ b/app/models/group.rb @@ -714,10 +714,6 @@ class Group < Namespace Gitlab::ServiceDesk.supported? && all_projects.service_desk_enabled.exists? end - def to_ability_name - model_name.singular - end - def activity_path Gitlab::Routing.url_helpers.activity_group_path(self) end diff --git a/app/models/issue.rb b/app/models/issue.rb index bbc484cc434..b7ccbe3ae12 100644 --- a/app/models/issue.rb +++ b/app/models/issue.rb @@ -544,6 +544,25 @@ class Issue < ApplicationRecord self.update_column(:upvotes_count, self.upvotes) end + # Returns `true` if the given User can read the current Issue. + # + # This method duplicates the same check of issue_policy.rb + # for performance reasons, check commit: 002ad215818450d2cbbc5fa065850a953dc7ada8 + # Make sure to sync this method with issue_policy.rb + def readable_by?(user) + if user.can_read_all_resources? + true + elsif project.owner == user + true + elsif confidential? && !assignee_or_author?(user) + project.team.member?(user, Gitlab::Access::REPORTER) + else + project.public? || + project.internal? && !user.external? || + project.team.member?(user) + end + end + private def spammable_attribute_changed? @@ -569,25 +588,6 @@ class Issue < ApplicationRecord Gitlab::UsageDataCounters::IssueActivityUniqueCounter.track_issue_created_action(author: author) end - # Returns `true` if the given User can read the current Issue. - # - # This method duplicates the same check of issue_policy.rb - # for performance reasons, check commit: 002ad215818450d2cbbc5fa065850a953dc7ada8 - # Make sure to sync this method with issue_policy.rb - def readable_by?(user) - if user.can_read_all_resources? - true - elsif project.owner == user - true - elsif confidential? && !assignee_or_author?(user) - project.team.member?(user, Gitlab::Access::REPORTER) - else - project.public? || - project.internal? && !user.external? || - project.team.member?(user) - end - end - # Returns `true` if this Issue is visible to everybody. def publicly_visible? project.public? && !confidential? && !::Gitlab::ExternalAuthorization.enabled? diff --git a/app/models/note.rb b/app/models/note.rb index 14e30168df8..5d630aa4984 100644 --- a/app/models/note.rb +++ b/app/models/note.rb @@ -384,12 +384,6 @@ class Note < ApplicationRecord super end - # This method is to be used for checking read permissions on a note instead of `system_note_with_references_visible_for?` - def readable_by?(user) - # note_policy accounts for #system_note_with_references_visible_for?(user) check when granting read access - Ability.allowed?(user, :read_note, self) - end - def award_emoji? can_be_award_emoji? && contains_emoji_only? end @@ -406,10 +400,6 @@ class Note < ApplicationRecord note =~ /\A#{Banzai::Filter::EmojiFilter.emoji_pattern}\s?\Z/ end - def to_ability_name - model_name.singular - end - def noteable_ability_name if for_snippet? 'snippet' diff --git a/app/models/project.rb b/app/models/project.rb index 1dd714c9def..5cad761ce2c 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -43,6 +43,8 @@ class Project < ApplicationRecord extend Gitlab::ConfigHelper + ignore_columns :container_registry_enabled, remove_after: '2021-09-22', remove_with: '14.4' + BoardLimitExceeded = Class.new(StandardError) ignore_columns :mirror_last_update_at, :mirror_last_successful_update_at, remove_after: '2021-09-22', remove_with: '14.4' @@ -1493,10 +1495,6 @@ class Project < ApplicationRecord end end - def to_ability_name - model_name.singular - end - # rubocop: disable CodeReuse/ServiceClass def execute_hooks(data, hooks_scope = :push_hooks) run_after_commit_or_now do diff --git a/app/policies/issue_policy.rb b/app/policies/issue_policy.rb index e58179e320d..053243e2296 100644 --- a/app/policies/issue_policy.rb +++ b/app/policies/issue_policy.rb @@ -44,7 +44,18 @@ class IssuePolicy < IssuablePolicy enable :update_subscription end - rule { ~persisted & can?(:guest_access) }.policy do + # admin can set metadata on new issues + rule { ~persisted & admin }.policy do + enable :set_issue_metadata + end + + # support bot needs to be able to set metadata on new issues when service desk is enabled + rule { ~persisted & support_bot & can?(:guest_access) }.policy do + enable :set_issue_metadata + end + + # guest members need to be able to set issue metadata per https://gitlab.com/gitlab-org/gitlab/-/issues/300100 + rule { ~persisted & is_project_member & can?(:guest_access) }.policy do enable :set_issue_metadata end diff --git a/app/policies/personal_access_token_policy.rb b/app/policies/personal_access_token_policy.rb index 1e5404b7822..31c973f575b 100644 --- a/app/policies/personal_access_token_policy.rb +++ b/app/policies/personal_access_token_policy.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true class PersonalAccessTokenPolicy < BasePolicy - condition(:is_owner) { user && subject.user_id == user.id } + condition(:is_owner) { user && subject.user_id == user.id && !subject.impersonation } rule { (is_owner | admin) & ~blocked }.policy do enable :read_token diff --git a/app/policies/project_policy.rb b/app/policies/project_policy.rb index 4dcd29382ce..526ccae36b0 100644 --- a/app/policies/project_policy.rb +++ b/app/policies/project_policy.rb @@ -284,6 +284,7 @@ class ProjectPolicy < BasePolicy enable :read_confidential_issues enable :read_package enable :read_product_analytics + enable :read_ci_cd_analytics end # We define `:public_user_access` separately because there are cases in gitlab-ee @@ -484,6 +485,7 @@ class ProjectPolicy < BasePolicy prevent(:read_insights) prevent(:read_cycle_analytics) prevent(:read_repository_graphs) + prevent(:read_ci_cd_analytics) end rule { wiki_disabled }.policy do @@ -559,6 +561,7 @@ class ProjectPolicy < BasePolicy enable :read_cycle_analytics enable :read_pages_content enable :read_analytics + enable :read_ci_cd_analytics enable :read_insights # NOTE: may be overridden by IssuePolicy @@ -666,6 +669,7 @@ class ProjectPolicy < BasePolicy rule { support_bot & ~service_desk_enabled }.policy do prevent :create_note prevent :read_project + prevent :guest_access end rule { project_bot }.enable :project_bot_access diff --git a/app/policies/todo_policy.rb b/app/policies/todo_policy.rb index d01a046c343..6237fbc50fa 100644 --- a/app/policies/todo_policy.rb +++ b/app/policies/todo_policy.rb @@ -5,7 +5,10 @@ class TodoPolicy < BasePolicy condition(:own_todo) do @user && @subject.user_id == @user.id end + condition(:can_read_target) do + @user && @subject.target&.readable_by?(@user) + end - rule { own_todo }.enable :read_todo - rule { own_todo }.enable :update_todo + rule { own_todo & can_read_target }.enable :read_todo + rule { own_todo & can_read_target }.enable :update_todo end diff --git a/app/services/issues/base_service.rb b/app/services/issues/base_service.rb index bf66a33a7b2..5e0a86fdeee 100644 --- a/app/services/issues/base_service.rb +++ b/app/services/issues/base_service.rb @@ -48,6 +48,9 @@ module Issues params.delete(:created_at) unless moved_issue || current_user.can?(:set_issue_created_at, project) params.delete(:updated_at) unless moved_issue || current_user.can?(:set_issue_updated_at, project) + # Only users with permission to handle error data can add it to issues + params.delete(:sentry_issue_attributes) unless current_user.can?(:update_sentry_issue, project) + issue.system_note_timestamp = params[:created_at] || params[:updated_at] end diff --git a/app/services/todos/allowed_target_filter_service.rb b/app/services/todos/allowed_target_filter_service.rb new file mode 100644 index 00000000000..dfed616710b --- /dev/null +++ b/app/services/todos/allowed_target_filter_service.rb @@ -0,0 +1,18 @@ +# frozen_string_literal: true + +module Todos + class AllowedTargetFilterService + include Gitlab::Allowable + + def initialize(todos, current_user) + @todos = todos + @current_user = current_user + end + + def execute + Preloaders::UserMaxAccessLevelInProjectsPreloader.new(@todos.map(&:project).compact, @current_user).execute + + @todos.select { |todo| can?(@current_user, :read_todo, todo) } + end + end +end diff --git a/app/views/admin/users/_head.html.haml b/app/views/admin/users/_head.html.haml index b7b712e078d..f4b1a2853f1 100644 --- a/app/views/admin/users/_head.html.haml +++ b/app/views/admin/users/_head.html.haml @@ -42,6 +42,7 @@ = link_to _("SSH keys"), keys_admin_user_path(@user) = nav_link(controller: :identities) do = link_to _("Identities"), admin_user_identities_path(@user) - = nav_link(controller: :impersonation_tokens) do - = link_to _("Impersonation Tokens"), admin_user_impersonation_tokens_path(@user) + - if impersonation_enabled? + = nav_link(controller: :impersonation_tokens) do + = link_to _("Impersonation Tokens"), admin_user_impersonation_tokens_path(@user) .gl-mb-3 diff --git a/app/views/dashboard/todos/index.html.haml b/app/views/dashboard/todos/index.html.haml index ca10861115b..58f817bf63b 100644 --- a/app/views/dashboard/todos/index.html.haml +++ b/app/views/dashboard/todos/index.html.haml @@ -25,7 +25,7 @@ = number_with_delimiter(todos_done_count) .nav-controls - - if @todos.any?(&:pending?) + - if @allowed_todos.any?(&:pending?) .gl-mr-3 = link_to destroy_all_dashboard_todos_path(todos_filter_params), class: 'gl-button btn btn-default btn-loading align-items-center js-todos-mark-all', method: :delete, data: { href: destroy_all_dashboard_todos_path(todos_filter_params) } do Mark all as done @@ -82,11 +82,11 @@ = sort_title_oldest_created .row.js-todos-all - - if @todos.any? + - if @allowed_todos.any? .col.js-todos-list-container{ data: { qa_selector: "todos_list_container" } } - .js-todos-options{ data: { per_page: @todos.limit_value, current_page: @todos.current_page, total_pages: @todos.total_pages } } + .js-todos-options{ data: { per_page: @allowed_todos.count, current_page: @todos.current_page, total_pages: @todos.total_pages } } %ul.content-list.todos-list - = render @todos + = render @allowed_todos = paginate @todos, theme: "gitlab" .js-nothing-here-container.empty-state.hidden .svg-content diff --git a/app/views/invites/show.html.haml b/app/views/invites/show.html.haml index ae13ef831dd..3622fc46983 100644 --- a/app/views/invites/show.html.haml +++ b/app/views/invites/show.html.haml @@ -1,29 +1,30 @@ - page_title _("Invitation") %h3.page-title= _("Invitation") -%p - = _("You have been invited") - - inviter = @member.created_by - - if inviter - = _("by") - = link_to inviter.name, user_url(inviter) - = _("to join %{source_name}") % { source_name: @invite_details[:title] } - %strong - = link_to @invite_details[:name], @invite_details[:url] - = _("as %{role}.") % { role: @member.human_access } +- if current_user_matches_invite? + - if member? + %p + = _("You are already a member of this %{member_source}.") % { member_source: @invite_details[:title] } + .actions + = link_to _("Go to %{source_name}") % { source_name: @invite_details[:title] }, @invite_details[:url], class: "btn gl-button btn-confirm" -- if member? - %p - = _("However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation.") % { member_source: @invite_details[:title] } + - else + %p + - inviter = @member.created_by + - link_to_inviter = link_to(inviter.name, user_url(inviter)) + - link_to_source = link_to(@invite_details[:name], @invite_details[:url]) + + = html_escape(_("You have been invited by %{link_to_inviter} to join %{source_name} %{strong_open}%{link_to_source}%{strong_close} as %{role}")) % { link_to_inviter: link_to_inviter, source_name: @invite_details[:title], strong_open: ''.html_safe, link_to_source: link_to_source, strong_close: ''.html_safe, role: @member.human_access } + + .actions + = link_to _("Accept invitation"), accept_invite_url(@token), method: :post, class: "btn gl-button btn-confirm" + = link_to _("Decline"), decline_invite_url(@token), method: :post, class: "btn gl-button btn-danger gl-ml-3" -- if !current_user_matches_invite? +- else %p - mail_to_invite_email = mail_to(@member.invite_email) - mail_to_current_user = mail_to(current_user.email) - link_to_current_user = link_to(current_user.to_reference, user_url(current_user)) - = _("Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}.").html_safe % { mail_to_invite_email: mail_to_invite_email, mail_to_current_user: mail_to_current_user, link_to_current_user: link_to_current_user } - -- if !member? - .actions - = link_to _("Accept invitation"), accept_invite_url(@token), method: :post, class: "btn gl-button btn-confirm" - = link_to _("Decline"), decline_invite_url(@token), method: :post, class: "btn gl-button btn-danger gl-ml-3" + = _("This invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}.").html_safe % { mail_to_invite_email: mail_to_invite_email, mail_to_current_user: mail_to_current_user, link_to_current_user: link_to_current_user } + %p + = _("Sign in as a user with the matching email address, add the email to this account, or sign-up for a new account using the matching email.") diff --git a/app/views/projects/empty.html.haml b/app/views/projects/empty.html.haml index 0fda74a3be5..70d86e79282 100644 --- a/app/views/projects/empty.html.haml +++ b/app/views/projects/empty.html.haml @@ -44,26 +44,26 @@ :preserve git clone #{ content_tag(:span, default_url_to_repo, class: 'js-clone')} cd #{h @project.path} - git switch -c #{default_branch_name} + git switch -c #{h default_branch_name} touch README.md git add README.md git commit -m "add README" - if @project.can_current_user_push_to_default_branch? %span>< - git push -u origin #{ default_branch_name } + git push -u origin #{h default_branch_name } %fieldset %h5= _('Push an existing folder') %pre.bg-light :preserve cd existing_folder - git init --initial-branch=#{default_branch_name} + git init --initial-branch=#{h default_branch_name} git remote add origin #{ content_tag(:span, default_url_to_repo, class: 'js-clone')} git add . git commit -m "Initial commit" - if @project.can_current_user_push_to_default_branch? %span>< - git push -u origin #{ default_branch_name } + git push -u origin #{h default_branch_name } %fieldset %h5= _('Push an existing Git repository') diff --git a/app/views/shared/_check_recovery_settings.html.haml b/app/views/shared/_check_recovery_settings.html.haml index 7ac90e5af03..99af540e9b7 100644 --- a/app/views/shared/_check_recovery_settings.html.haml +++ b/app/views/shared/_check_recovery_settings.html.haml @@ -1,6 +1,10 @@ -.gl-alert.gl-alert-warning.js-recovery-settings-callout{ role: 'alert', data: { feature_id: "account_recovery_regular_check", dismiss_endpoint: user_callouts_path, defer_links: "true" } } - %button.js-close.gl-alert-dismiss.gl-cursor-pointer{ type: 'button', 'aria-label' => _('Dismiss') } - = sprite_icon('close', css_class: 'gl-icon') += render 'shared/global_alert', + variant: :warning, + alert_class: 'js-recovery-settings-callout', + alert_data: { feature_id: 'account_recovery_regular_check', dismiss_endpoint: user_callouts_path, defer_links: 'true' } do .gl-alert-body - - account_link_start = ''.html_safe % { url: profile_account_path } - = _("Please ensure your account's %{account_link_start}recovery settings%{account_link_end} are up to date.").html_safe % { account_link_start: account_link_start, account_link_end: ''.html_safe } + = s_('Profiles|We recommend you ensure two-factor authentication is enabled and the settings are up to date.') + = link_to _('Learn more.'), help_page_path('user/profile/account/two_factor_authentication'), target: '_blank', rel: 'noopener noreferrer' + .gl-alert-actions + = link_to profile_two_factor_auth_path, class: 'deferred-link btn gl-alert-action btn-confirm btn-md gl-button' do + = s_('Profiles|Manage two-factor authentication') -- cgit v1.2.3