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
path: root/app
diff options
context:
space:
mode:
Diffstat (limited to 'app')
-rw-r--r--app/assets/javascripts/pages/projects/find_file/ref_switcher/index.js38
-rw-r--r--app/assets/javascripts/pages/projects/find_file/ref_switcher/ref_switcher_utils.js28
-rw-r--r--app/assets/javascripts/pages/projects/find_file/show/index.js2
-rw-r--r--app/assets/javascripts/work_items/components/work_item_comment_form.vue4
-rw-r--r--app/assets/javascripts/work_items/components/work_item_notes.vue20
-rw-r--r--app/assets/javascripts/work_items/graphql/cache_utils.js14
-rw-r--r--app/graphql/types/ci/runner_type.rb15
-rw-r--r--app/models/ci/runner.rb4
-rw-r--r--app/policies/ci/runner_policy.rb6
-rw-r--r--app/views/projects/find_file/show.html.haml2
10 files changed, 114 insertions, 19 deletions
diff --git a/app/assets/javascripts/pages/projects/find_file/ref_switcher/index.js b/app/assets/javascripts/pages/projects/find_file/ref_switcher/index.js
new file mode 100644
index 00000000000..9a3bb25de70
--- /dev/null
+++ b/app/assets/javascripts/pages/projects/find_file/ref_switcher/index.js
@@ -0,0 +1,38 @@
+import Vue from 'vue';
+import { s__ } from '~/locale';
+import Translate from '~/vue_shared/translate';
+import RefSelector from '~/ref/components/ref_selector.vue';
+import { visitUrl } from '~/lib/utils/url_utility';
+import { generateRefDestinationPath } from './ref_switcher_utils';
+
+Vue.use(Translate);
+
+const REF_SWITCH_HEADER = s__('FindFile|Switch branch/tag');
+
+export default () => {
+ const el = document.getElementById('js-blob-ref-switcher');
+ if (!el) return false;
+
+ const { projectId, ref, namespace } = el.dataset;
+
+ return new Vue({
+ el,
+ render(createElement) {
+ return createElement(RefSelector, {
+ props: {
+ projectId,
+ value: ref,
+ translations: {
+ dropdownHeader: REF_SWITCH_HEADER,
+ searchPlaceholder: REF_SWITCH_HEADER,
+ },
+ },
+ on: {
+ input(selected) {
+ visitUrl(generateRefDestinationPath(selected, namespace));
+ },
+ },
+ });
+ },
+ });
+};
diff --git a/app/assets/javascripts/pages/projects/find_file/ref_switcher/ref_switcher_utils.js b/app/assets/javascripts/pages/projects/find_file/ref_switcher/ref_switcher_utils.js
new file mode 100644
index 00000000000..5fecd024f1a
--- /dev/null
+++ b/app/assets/javascripts/pages/projects/find_file/ref_switcher/ref_switcher_utils.js
@@ -0,0 +1,28 @@
+import { joinPaths } from '~/lib/utils/url_utility';
+
+/**
+ * Generates a ref destination url based on the selected ref and current url.
+ * @param {string} selectedRef - The selected ref from the ref dropdown.
+ * @param {string} namespace - The destination namespace for the path.
+ */
+export function generateRefDestinationPath(selectedRef, namespace) {
+ if (!selectedRef || !namespace) {
+ return window.location.href;
+ }
+
+ const { pathname } = window.location;
+ const encodedHash = '%23';
+
+ const [projectRootPath] = pathname.split(namespace);
+
+ const destinationPath = joinPaths(
+ projectRootPath,
+ namespace,
+ encodeURI(selectedRef).replace(/#/g, encodedHash),
+ );
+
+ const newURL = new URL(window.location);
+ newURL.pathname = destinationPath;
+
+ return newURL.href;
+}
diff --git a/app/assets/javascripts/pages/projects/find_file/show/index.js b/app/assets/javascripts/pages/projects/find_file/show/index.js
index f47888f0cb8..e207df2434b 100644
--- a/app/assets/javascripts/pages/projects/find_file/show/index.js
+++ b/app/assets/javascripts/pages/projects/find_file/show/index.js
@@ -1,7 +1,9 @@
import $ from 'jquery';
import ShortcutsFindFile from '~/behaviors/shortcuts/shortcuts_find_file';
import ProjectFindFile from '~/projects/project_find_file';
+import InitBlobRefSwitcher from '../ref_switcher';
+InitBlobRefSwitcher();
const findElement = document.querySelector('.js-file-finder');
const projectFindFile = new ProjectFindFile($('.file-finder-holder'), {
url: findElement.dataset.fileFindUrl,
diff --git a/app/assets/javascripts/work_items/components/work_item_comment_form.vue b/app/assets/javascripts/work_items/components/work_item_comment_form.vue
index 9da4473cd46..a38fea01d1f 100644
--- a/app/assets/javascripts/work_items/components/work_item_comment_form.vue
+++ b/app/assets/javascripts/work_items/components/work_item_comment_form.vue
@@ -175,7 +175,7 @@ export default {
this.isSubmitting = true;
this.$emit('replying', this.commentText);
- const { queryVariables, fetchByIid, sortOrder } = this;
+ const { queryVariables, fetchByIid } = this;
try {
this.track('add_work_item_comment');
@@ -193,7 +193,7 @@ export default {
if (createNoteData.data?.createNote?.errors?.length) {
throw new Error(createNoteData.data?.createNote?.errors[0]);
}
- updateCommentState(store, createNoteData, fetchByIid, queryVariables, sortOrder);
+ updateCommentState(store, createNoteData, fetchByIid, queryVariables);
},
});
clearDraft(this.autosaveKey);
diff --git a/app/assets/javascripts/work_items/components/work_item_notes.vue b/app/assets/javascripts/work_items/components/work_item_notes.vue
index 474fea5cec6..457eabb5671 100644
--- a/app/assets/javascripts/work_items/components/work_item_notes.vue
+++ b/app/assets/javascripts/work_items/components/work_item_notes.vue
@@ -50,7 +50,6 @@ export default {
},
data() {
return {
- notesArray: [],
isLoadingMore: false,
perPage: DEFAULT_PAGE_SIZE_NOTES,
sortOrder: ASC,
@@ -61,12 +60,12 @@ export default {
initialLoading() {
return this.$apollo.queries.workItemNotes.loading && !this.isLoadingMore;
},
- pageInfo() {
- return this.workItemNotes?.pageInfo;
- },
avatarUrl() {
return window.gon.current_user_avatar_url;
},
+ pageInfo() {
+ return this.workItemNotes?.pageInfo;
+ },
hasNextPage() {
return this.pageInfo?.hasNextPage;
},
@@ -95,6 +94,14 @@ export default {
sortOrder: this.sortOrder,
};
},
+ notesArray() {
+ const notes = this.workItemNotes?.nodes || [];
+
+ if (this.sortOrder === DESC) {
+ return [...notes].reverse();
+ }
+ return notes;
+ },
},
apollo: {
workItemNotes: {
@@ -117,8 +124,6 @@ export default {
: data.workItem?.widgets;
const discussionNodes =
workItemWidgets.find((widget) => widget.type === 'NOTES')?.discussions || [];
- this.notesArray = discussionNodes?.nodes || [];
- this.updateSortingOrderIfApplicable();
return discussionNodes;
},
skip() {
@@ -128,6 +133,8 @@ export default {
this.$emit('error', i18n.fetchError);
},
result() {
+ this.updateSortingOrderIfApplicable();
+
if (this.hasNextPage) {
this.fetchMoreNotes();
}
@@ -163,7 +170,6 @@ export default {
},
changeNotesSortOrder(direction) {
this.sortOrder = direction;
- this.notesArray = [...this.notesArray].reverse();
this.changeNotesSortOrderAfterLoading = false;
},
async fetchMoreNotes() {
diff --git a/app/assets/javascripts/work_items/graphql/cache_utils.js b/app/assets/javascripts/work_items/graphql/cache_utils.js
index c1de9f673f2..16b892b3476 100644
--- a/app/assets/javascripts/work_items/graphql/cache_utils.js
+++ b/app/assets/javascripts/work_items/graphql/cache_utils.js
@@ -1,6 +1,5 @@
import { produce } from 'immer';
import { WIDGET_TYPE_NOTES } from '~/work_items/constants';
-import { ASC } from '~/notes/constants';
import { getWorkItemNotesQuery } from '~/work_items/utils';
/**
@@ -12,13 +11,7 @@ import { getWorkItemNotesQuery } from '~/work_items/utils';
* @param queryVariables
* @param sortOrder
*/
-export const updateCommentState = (
- store,
- { data: { createNote } },
- fetchByIid,
- queryVariables,
- sortOrder,
-) => {
+export const updateCommentState = (store, { data: { createNote } }, fetchByIid, queryVariables) => {
const notesQuery = getWorkItemNotesQuery(fetchByIid);
const variables = {
...queryVariables,
@@ -36,7 +29,10 @@ export const updateCommentState = (
)
: draftData.workItem.widgets.find((widget) => widget.type === WIDGET_TYPE_NOTES);
- const arrayPushMethod = sortOrder === ASC ? 'push' : 'unshift';
+ // as notes are currently sorted/reversed on the frontend rather than in the query
+ // we only ever push.
+ // const arrayPushMethod = sortOrder === ASC ? 'push' : 'unshift';
+ const arrayPushMethod = 'push';
// manual update of cache with a completely new discussion
if (createNote.note.discussion.notes.nodes.length === 1) {
diff --git a/app/graphql/types/ci/runner_type.rb b/app/graphql/types/ci/runner_type.rb
index 35339624e37..3cab2b7aba7 100644
--- a/app/graphql/types/ci/runner_type.rb
+++ b/app/graphql/types/ci/runner_type.rb
@@ -14,6 +14,9 @@ module Types
JOB_COUNT_LIMIT = 1000
+ # Only allow ephemeral_authentication_token to be visible for a short while
+ RUNNER_EPHEMERAL_TOKEN_AVAILABILITY_TIME = 3.hours
+
alias_method :runner, :object
field :access_level, ::Types::Ci::RunnerAccessLevelEnum, null: false,
@@ -35,6 +38,10 @@ module Types
description: 'Description of the runner.'
field :edit_admin_url, GraphQL::Types::String, null: true,
description: 'Admin form URL of the runner. Only available for administrators.'
+ field :ephemeral_authentication_token, GraphQL::Types::String, null: true,
+ description: 'Ephemeral authentication token used for runner machine registration.',
+ authorize: :read_ephemeral_token,
+ alpha: { milestone: '15.9' }
field :executor_name, GraphQL::Types::String, null: true,
description: 'Executor last advertised by the runner.',
method: :executor_name
@@ -134,6 +141,14 @@ module Types
Gitlab::Routing.url_helpers.edit_admin_runner_url(runner) if can_admin_runners?
end
+ def ephemeral_authentication_token
+ return unless runner.created_via_ui?
+ return unless runner.created_at > RUNNER_EPHEMERAL_TOKEN_AVAILABILITY_TIME.ago
+ return if runner.runner_machines.any?
+
+ runner.token
+ end
+
def project_count
BatchLoader::GraphQL.for(runner.id).batch(key: :runner_project_count) do |ids, loader, args|
counts = ::Ci::Runner.project_type
diff --git a/app/models/ci/runner.rb b/app/models/ci/runner.rb
index 5c4512c5f72..19acd86a7f4 100644
--- a/app/models/ci/runner.rb
+++ b/app/models/ci/runner.rb
@@ -495,6 +495,10 @@ module Ci
"#{CREATED_RUNNER_TOKEN_PREFIX}#{token}"
end
+ def created_via_ui?
+ token.start_with?(CREATED_RUNNER_TOKEN_PREFIX)
+ end
+
private
scope :with_upgrade_status, ->(upgrade_status) do
diff --git a/app/policies/ci/runner_policy.rb b/app/policies/ci/runner_policy.rb
index 1c23b367489..7b01dccff87 100644
--- a/app/policies/ci/runner_policy.rb
+++ b/app/policies/ci/runner_policy.rb
@@ -9,6 +9,10 @@ module Ci
@user.owns_runner?(@subject)
end
+ condition(:creator) do
+ @user == @subject.creator
+ end
+
with_options scope: :subject, score: 0
condition(:is_instance_runner) do
@subject.instance_type?
@@ -72,6 +76,8 @@ module Ci
rule { ~admin & belongs_to_multiple_projects }.prevent :delete_runner
rule { ~admin & locked }.prevent :assign_runner
+
+ rule { creator }.enable :read_ephemeral_token
end
end
diff --git a/app/views/projects/find_file/show.html.haml b/app/views/projects/find_file/show.html.haml
index 7cd4ab08680..1d4e907dd61 100644
--- a/app/views/projects/find_file/show.html.haml
+++ b/app/views/projects/find_file/show.html.haml
@@ -4,7 +4,7 @@
.file-finder-holder.tree-holder.clearfix.js-file-finder{ 'data-file-find-url': "#{escape_javascript(project_files_path(@project, @ref, format: :json))}", 'data-find-tree-url': escape_javascript(project_tree_path(@project, @ref)), 'data-blob-url-template': escape_javascript(project_blob_path(@project, @ref)) }
.nav-block
.tree-ref-holder
- = render 'shared/ref_switcher', destination: 'find_file', path: @path
+ #js-blob-ref-switcher{ data: { project_id: @project.id, ref: @ref, namespace: "/-/find_file" } }
%ul.breadcrumb.repo-breadcrumb
%li.breadcrumb-item
= link_to project_tree_path(@project, @ref) do