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:
authorGitLab Bot <gitlab-bot@gitlab.com>2021-04-14 12:09:14 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2021-04-14 12:09:14 +0300
commit4ab67d65296979ba6f5fca3142b86460b748590e (patch)
treecbaa126a09126f2e43ba006c30dc8175858573e3 /app
parent90fa047c0dbb0a5e97c384fa6c45991c04acba5f (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app')
-rw-r--r--app/assets/javascripts/lib/utils/webpack.js6
-rw-r--r--app/assets/javascripts/packages/list/components/package_title.vue10
-rw-r--r--app/assets/javascripts/packages/list/components/packages_list_app.vue47
-rw-r--r--app/assets/javascripts/packages/list/packages_list_app_bundle.js8
-rw-r--r--app/assets/javascripts/packages/shared/components/package_icon_and_name.vue17
-rw-r--r--app/assets/javascripts/packages/shared/components/package_list_row.vue22
-rw-r--r--app/assets/javascripts/packages_and_registries/infrastructure_registry/components/infrastructure_icon_and_name.vue17
-rw-r--r--app/assets/javascripts/packages_and_registries/infrastructure_registry/components/infrastructure_search.vue45
-rw-r--r--app/assets/javascripts/packages_and_registries/infrastructure_registry/components/infrastructure_title.vue53
-rw-r--r--app/assets/javascripts/packages_and_registries/infrastructure_registry/list_app_bundle.js33
-rw-r--r--app/assets/javascripts/pages/admin/admin.js13
-rw-r--r--app/assets/javascripts/pages/admin/application_settings/general/components/signup_checkbox.vue50
-rw-r--r--app/assets/javascripts/pages/admin/application_settings/general/components/signup_form.vue331
-rw-r--r--app/assets/javascripts/pages/admin/application_settings/general/index.js26
-rw-r--r--app/assets/javascripts/pages/admin/application_settings/gitpod.js24
-rw-r--r--app/assets/javascripts/pages/admin/application_settings/signup_restrictions.js31
-rw-r--r--app/assets/javascripts/pages/admin/application_settings/utils.js21
-rw-r--r--app/assets/javascripts/pages/projects/packages/infrastructure_registry/index/index.js4
-rw-r--r--app/assets/stylesheets/pages/runners.scss14
-rw-r--r--app/helpers/ci/runners_helper.rb31
-rw-r--r--app/models/namespaces/traversal/recursive.rb5
-rw-r--r--app/views/admin/application_settings/_signup.html.haml98
-rw-r--r--app/views/projects/packages/infrastructure_registry/index.html.haml6
-rw-r--r--app/views/projects/runners/_runner.html.haml2
-rw-r--r--app/workers/all_queues.yml2
-rw-r--r--app/workers/update_highest_role_worker.rb2
26 files changed, 738 insertions, 180 deletions
diff --git a/app/assets/javascripts/lib/utils/webpack.js b/app/assets/javascripts/lib/utils/webpack.js
index 07a4d2deb0b..a88f1bd82fc 100644
--- a/app/assets/javascripts/lib/utils/webpack.js
+++ b/app/assets/javascripts/lib/utils/webpack.js
@@ -11,10 +11,4 @@ export function resetServiceWorkersPublicPath() {
const relativeRootPath = (gon && gon.relative_url_root) || '';
const webpackAssetPath = joinPaths(relativeRootPath, '/assets/webpack/');
__webpack_public_path__ = webpackAssetPath; // eslint-disable-line babel/camelcase
-
- // monaco-editor-webpack-plugin currently (incorrectly) references the
- // public path as a property of `window`. Once this is fixed upstream we
- // can remove this line
- // see: https://github.com/Microsoft/monaco-editor-webpack-plugin/pull/63
- window.__webpack_public_path__ = webpackAssetPath; // eslint-disable-line
}
diff --git a/app/assets/javascripts/packages/list/components/package_title.vue b/app/assets/javascripts/packages/list/components/package_title.vue
index 6176e15ffd4..426ad150ea9 100644
--- a/app/assets/javascripts/packages/list/components/package_title.vue
+++ b/app/assets/javascripts/packages/list/components/package_title.vue
@@ -11,25 +11,25 @@ export default {
MetadataItem,
},
props: {
- packagesCount: {
+ count: {
type: Number,
required: false,
default: null,
},
- packageHelpUrl: {
+ helpUrl: {
type: String,
required: true,
},
},
computed: {
showPackageCount() {
- return Number.isInteger(this.packagesCount);
+ return Number.isInteger(this.count);
},
packageAmountText() {
- return n__(`%d Package`, `%d Packages`, this.packagesCount);
+ return n__(`%d Package`, `%d Packages`, this.count);
},
infoMessages() {
- return [{ text: LIST_INTRO_TEXT, link: this.packageHelpUrl }];
+ return [{ text: LIST_INTRO_TEXT, link: this.helpUrl }];
},
},
i18n: {
diff --git a/app/assets/javascripts/packages/list/components/packages_list_app.vue b/app/assets/javascripts/packages/list/components/packages_list_app.vue
index b9d922bf1cf..4c5fb0ee7c9 100644
--- a/app/assets/javascripts/packages/list/components/packages_list_app.vue
+++ b/app/assets/javascripts/packages/list/components/packages_list_app.vue
@@ -8,8 +8,6 @@ import { SHOW_DELETE_SUCCESS_ALERT } from '~/packages/shared/constants';
import { FILTERED_SEARCH_TERM } from '~/packages_and_registries/shared/constants';
import { getQueryParams, extractFilterAndSorting } from '~/packages_and_registries/shared/utils';
import { DELETE_PACKAGE_SUCCESS_MESSAGE } from '../constants';
-import PackageSearch from './package_search.vue';
-import PackageTitle from './package_title.vue';
import PackageList from './packages_list.vue';
export default {
@@ -18,8 +16,38 @@ export default {
GlLink,
GlSprintf,
PackageList,
- PackageTitle,
- PackageSearch,
+ PackageTitle: () =>
+ import(/* webpackChunkName: 'package_registry_components' */ './package_title.vue'),
+ PackageSearch: () =>
+ import(/* webpackChunkName: 'package_registry_components' */ './package_search.vue'),
+ InfrastructureTitle: () =>
+ import(
+ /* webpackChunkName: 'infrastructure_registry_components' */ '~/packages_and_registries/infrastructure_registry/components/infrastructure_title.vue'
+ ),
+ InfrastructureSearch: () =>
+ import(
+ /* webpackChunkName: 'infrastructure_registry_components' */ '~/packages_and_registries/infrastructure_registry/components/infrastructure_search.vue'
+ ),
+ },
+ inject: {
+ titleComponent: {
+ from: 'titleComponent',
+ default: 'PackageTitle',
+ },
+ searchComponent: {
+ from: 'searchComponent',
+ default: 'PackageSearch',
+ },
+ emptyPageTitle: {
+ from: 'emptyPageTitle',
+ default: s__('PackageRegistry|There are no packages yet'),
+ },
+ noResultsText: {
+ from: 'noResultsText',
+ default: s__(
+ 'PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab.',
+ ),
+ },
},
computed: {
...mapState({
@@ -38,7 +66,7 @@ export default {
emptyStateTitle() {
return this.emptySearch
- ? s__('PackageRegistry|There are no packages yet')
+ ? this.emptyPageTitle
: s__('PackageRegistry|Sorry, your filter produced no results');
},
},
@@ -77,24 +105,21 @@ export default {
},
i18n: {
widenFilters: s__('PackageRegistry|To widen your search, change or remove the filters above.'),
- noResults: s__(
- 'PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab.',
- ),
},
};
</script>
<template>
<div>
- <package-title :package-help-url="packageHelpUrl" :packages-count="packagesCount" />
- <package-search @update="requestPackagesList" />
+ <component :is="titleComponent" :help-url="packageHelpUrl" :count="packagesCount" />
+ <component :is="searchComponent" @update="requestPackagesList" />
<package-list @page:changed="onPageChanged" @package:delete="onPackageDeleteRequest">
<template #empty-state>
<gl-empty-state :title="emptyStateTitle" :svg-path="emptyListIllustration">
<template #description>
<gl-sprintf v-if="!emptySearch" :message="$options.i18n.widenFilters" />
- <gl-sprintf v-else :message="$options.i18n.noResults">
+ <gl-sprintf v-else :message="noResultsText">
<template #noPackagesLink="{ content }">
<gl-link :href="emptyListHelpUrl" target="_blank">{{ content }}</gl-link>
</template>
diff --git a/app/assets/javascripts/packages/list/packages_list_app_bundle.js b/app/assets/javascripts/packages/list/packages_list_app_bundle.js
index 58b09c1ebd1..2911cf70a33 100644
--- a/app/assets/javascripts/packages/list/packages_list_app_bundle.js
+++ b/app/assets/javascripts/packages/list/packages_list_app_bundle.js
@@ -1,11 +1,8 @@
import Vue from 'vue';
-import VueApollo from 'vue-apollo';
-import createDefaultClient from '~/lib/graphql';
import Translate from '~/vue_shared/translate';
import PackagesListApp from './components/packages_list_app.vue';
import { createStore } from './stores';
-Vue.use(VueApollo);
Vue.use(Translate);
export default () => {
@@ -13,14 +10,9 @@ export default () => {
const store = createStore();
store.dispatch('setInitialState', el.dataset);
- const apolloProvider = new VueApollo({
- defaultClient: createDefaultClient(),
- });
-
return new Vue({
el,
store,
- apolloProvider,
components: {
PackagesListApp,
},
diff --git a/app/assets/javascripts/packages/shared/components/package_icon_and_name.vue b/app/assets/javascripts/packages/shared/components/package_icon_and_name.vue
new file mode 100644
index 00000000000..105f7bbe132
--- /dev/null
+++ b/app/assets/javascripts/packages/shared/components/package_icon_and_name.vue
@@ -0,0 +1,17 @@
+<script>
+import { GlIcon } from '@gitlab/ui';
+
+export default {
+ name: 'PackageIconAndName',
+ components: {
+ GlIcon,
+ },
+};
+</script>
+
+<template>
+ <div class="gl-display-flex gl-align-items-center">
+ <gl-icon name="package" class="gl-ml-3 gl-mr-2" />
+ <span><slot></slot></span>
+ </div>
+</template>
diff --git a/app/assets/javascripts/packages/shared/components/package_list_row.vue b/app/assets/javascripts/packages/shared/components/package_list_row.vue
index 172b356227a..4de4c191e51 100644
--- a/app/assets/javascripts/packages/shared/components/package_list_row.vue
+++ b/app/assets/javascripts/packages/shared/components/package_list_row.vue
@@ -1,5 +1,5 @@
<script>
-import { GlButton, GlIcon, GlLink, GlSprintf, GlTooltipDirective, GlTruncate } from '@gitlab/ui';
+import { GlButton, GlLink, GlSprintf, GlTooltipDirective, GlTruncate } from '@gitlab/ui';
import ListItem from '~/vue_shared/components/registry/list_item.vue';
import timeagoMixin from '~/vue_shared/mixins/timeago';
import { getPackageTypeLabel } from '../utils';
@@ -11,7 +11,6 @@ export default {
name: 'PackageListRow',
components: {
GlButton,
- GlIcon,
GlLink,
GlSprintf,
GlTruncate,
@@ -19,11 +18,23 @@ export default {
PackagePath,
PublishMethod,
ListItem,
+ PackageIconAndName: () =>
+ import(/* webpackChunkName: 'package_registry_components' */ './package_icon_and_name.vue'),
+ InfrastructureIconAndName: () =>
+ import(
+ /* webpackChunkName: 'infrastructure_registry_components' */ '~/packages_and_registries/infrastructure_registry/components/infrastructure_icon_and_name.vue'
+ ),
},
directives: {
GlTooltip: GlTooltipDirective,
},
mixins: [timeagoMixin],
+ inject: {
+ iconComponent: {
+ from: 'iconComponent',
+ default: 'PackageIconAndName',
+ },
+ },
props: {
packageEntity: {
type: Object,
@@ -94,10 +105,9 @@ export default {
</gl-sprintf>
</div>
- <div v-if="showPackageType" class="d-flex align-items-center" data-testid="package-type">
- <gl-icon name="package" class="gl-ml-3 gl-mr-2" />
- <span>{{ packageType }}</span>
- </div>
+ <component :is="iconComponent" v-if="showPackageType">
+ {{ packageType }}
+ </component>
<package-path v-if="hasProjectLink" :path="packageEntity.project_path" />
</div>
diff --git a/app/assets/javascripts/packages_and_registries/infrastructure_registry/components/infrastructure_icon_and_name.vue b/app/assets/javascripts/packages_and_registries/infrastructure_registry/components/infrastructure_icon_and_name.vue
new file mode 100644
index 00000000000..3100a1a7296
--- /dev/null
+++ b/app/assets/javascripts/packages_and_registries/infrastructure_registry/components/infrastructure_icon_and_name.vue
@@ -0,0 +1,17 @@
+<script>
+import { GlIcon } from '@gitlab/ui';
+
+export default {
+ name: 'InfrastructureIconAndName',
+ components: {
+ GlIcon,
+ },
+};
+</script>
+
+<template>
+ <div class="gl-display-flex gl-align-items-center">
+ <gl-icon name="infrastructure-registry" class="gl-ml-3 gl-mr-2" />
+ <span>{{ s__('InfrastructureRegistry|Terraform') }}</span>
+ </div>
+</template>
diff --git a/app/assets/javascripts/packages_and_registries/infrastructure_registry/components/infrastructure_search.vue b/app/assets/javascripts/packages_and_registries/infrastructure_registry/components/infrastructure_search.vue
new file mode 100644
index 00000000000..2ed17208404
--- /dev/null
+++ b/app/assets/javascripts/packages_and_registries/infrastructure_registry/components/infrastructure_search.vue
@@ -0,0 +1,45 @@
+<script>
+import { mapState, mapActions } from 'vuex';
+import { LIST_KEY_PACKAGE_TYPE } from '~/packages/list/constants';
+import getTableHeaders from '~/packages/list/utils';
+import RegistrySearch from '~/vue_shared/components/registry/registry_search.vue';
+import UrlSync from '~/vue_shared/components/url_sync.vue';
+
+export default {
+ components: { RegistrySearch, UrlSync },
+ computed: {
+ ...mapState({
+ isGroupPage: (state) => state.config.isGroupPage,
+ sorting: (state) => state.sorting,
+ filter: (state) => state.filter,
+ }),
+ sortableFields() {
+ return getTableHeaders(this.isGroupPage).filter((h) => h.orderBy !== LIST_KEY_PACKAGE_TYPE);
+ },
+ },
+ methods: {
+ ...mapActions(['setSorting', 'setFilter']),
+ updateSorting(newValue) {
+ this.setSorting(newValue);
+ this.$emit('update');
+ },
+ },
+};
+</script>
+
+<template>
+ <url-sync>
+ <template #default="{ updateQuery }">
+ <registry-search
+ :filter="filter"
+ :sorting="sorting"
+ :tokens="[]"
+ :sortable-fields="sortableFields"
+ @sorting:changed="updateSorting"
+ @filter:changed="setFilter"
+ @filter:submit="$emit('update')"
+ @query:changed="updateQuery"
+ />
+ </template>
+ </url-sync>
+</template>
diff --git a/app/assets/javascripts/packages_and_registries/infrastructure_registry/components/infrastructure_title.vue b/app/assets/javascripts/packages_and_registries/infrastructure_registry/components/infrastructure_title.vue
new file mode 100644
index 00000000000..2a479c65d0c
--- /dev/null
+++ b/app/assets/javascripts/packages_and_registries/infrastructure_registry/components/infrastructure_title.vue
@@ -0,0 +1,53 @@
+<script>
+import { s__, n__ } from '~/locale';
+import MetadataItem from '~/vue_shared/components/registry/metadata_item.vue';
+import TitleArea from '~/vue_shared/components/registry/title_area.vue';
+
+export default {
+ name: 'InfrastructureTitle',
+ components: {
+ TitleArea,
+ MetadataItem,
+ },
+ props: {
+ count: {
+ type: Number,
+ required: false,
+ default: null,
+ },
+ helpUrl: {
+ type: String,
+ required: true,
+ },
+ },
+ computed: {
+ showModuleCount() {
+ return Number.isInteger(this.count);
+ },
+ moduleAmountText() {
+ return n__(`%d Module`, `%d Modules`, this.count);
+ },
+ infoMessages() {
+ return [{ text: this.$options.i18n.LIST_INTRO_TEXT, link: this.helpUrl }];
+ },
+ },
+ i18n: {
+ LIST_TITLE_TEXT: s__('InfrastructureRegistry|Infrastructure Registry'),
+ LIST_INTRO_TEXT: s__(
+ 'InfrastructureRegistry|Publish and share your modules. %{docLinkStart}More information%{docLinkEnd}',
+ ),
+ },
+};
+</script>
+
+<template>
+ <title-area :title="$options.i18n.LIST_TITLE_TEXT" :info-messages="infoMessages">
+ <template #metadata-amount>
+ <metadata-item
+ v-if="showModuleCount"
+ icon="infrastructure-registry"
+ :text="moduleAmountText"
+ />
+ </template>
+ </title-area>
+</template>
diff --git a/app/assets/javascripts/packages_and_registries/infrastructure_registry/list_app_bundle.js b/app/assets/javascripts/packages_and_registries/infrastructure_registry/list_app_bundle.js
new file mode 100644
index 00000000000..88ee8a4200e
--- /dev/null
+++ b/app/assets/javascripts/packages_and_registries/infrastructure_registry/list_app_bundle.js
@@ -0,0 +1,33 @@
+import Vue from 'vue';
+import { s__ } from '~/locale';
+import PackagesListApp from '~/packages/list/components/packages_list_app.vue';
+import { createStore } from '~/packages/list/stores';
+import Translate from '~/vue_shared/translate';
+
+Vue.use(Translate);
+
+export default () => {
+ const el = document.getElementById('js-vue-packages-list');
+ const store = createStore();
+ store.dispatch('setInitialState', el.dataset);
+
+ return new Vue({
+ el,
+ store,
+ components: {
+ PackagesListApp,
+ },
+ provide: {
+ titleComponent: 'InfrastructureTitle',
+ searchComponent: 'InfrastructureSearch',
+ iconComponent: 'InfrastructureIconAndName',
+ emptyPageTitle: s__('InfrastructureRegistry|You have no Terraform modules in your project'),
+ noResultsText: s__(
+ 'InfrastructureRegistry|Terraform modules are the main way to package and reuse resource configurations with Terraform. Learn more about how to %{noPackagesLinkStart}create Terraform modules%{noPackagesLinkEnd} in GitLab.',
+ ),
+ },
+ render(createElement) {
+ return createElement('packages-list-app');
+ },
+ });
+};
diff --git a/app/assets/javascripts/pages/admin/admin.js b/app/assets/javascripts/pages/admin/admin.js
index 2732fc191be..6b7bfbf217d 100644
--- a/app/assets/javascripts/pages/admin/admin.js
+++ b/app/assets/javascripts/pages/admin/admin.js
@@ -1,16 +1,6 @@
import $ from 'jquery';
import { refreshCurrentPage } from '../../lib/utils/url_utility';
-function showDenylistType() {
- if ($('input[name="denylist_type"]:checked').val() === 'file') {
- $('.js-denylist-file').show();
- $('.js-denylist-raw').hide();
- } else {
- $('.js-denylist-file').hide();
- $('.js-denylist-raw').show();
- }
-}
-
export default function adminInit() {
$('input#user_force_random_password').on('change', function randomPasswordClick() {
const $elems = $('#user_password, #user_password_confirmation');
@@ -27,7 +17,4 @@ export default function adminInit() {
});
$('li.project_member, li.group_member').on('ajax:success', refreshCurrentPage);
-
- $("input[name='denylist_type']").on('click', showDenylistType);
- showDenylistType();
}
diff --git a/app/assets/javascripts/pages/admin/application_settings/general/components/signup_checkbox.vue b/app/assets/javascripts/pages/admin/application_settings/general/components/signup_checkbox.vue
new file mode 100644
index 00000000000..2217792d7f3
--- /dev/null
+++ b/app/assets/javascripts/pages/admin/application_settings/general/components/signup_checkbox.vue
@@ -0,0 +1,50 @@
+<script>
+import { GlFormCheckbox } from '@gitlab/ui';
+
+export default {
+ components: {
+ GlFormCheckbox,
+ },
+ props: {
+ name: {
+ type: String,
+ required: true,
+ },
+ helpText: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ label: {
+ type: String,
+ required: true,
+ },
+ value: {
+ type: Boolean,
+ required: true,
+ },
+ dataQaSelector: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ },
+};
+</script>
+
+<template>
+ <div>
+ <input :name="name" type="hidden" :value="value ? '1' : '0'" data-testid="input" />
+
+ <gl-form-checkbox
+ :checked="value"
+ :data-qa-selector="dataQaSelector"
+ @input="$emit('input', $event)"
+ >
+ <span data-testid="label">{{ label }}</span>
+ <template v-if="helpText" #help>
+ <span data-testid="helpText">{{ helpText }}</span>
+ </template>
+ </gl-form-checkbox>
+ </div>
+</template>
diff --git a/app/assets/javascripts/pages/admin/application_settings/general/components/signup_form.vue b/app/assets/javascripts/pages/admin/application_settings/general/components/signup_form.vue
new file mode 100644
index 00000000000..e9091d30523
--- /dev/null
+++ b/app/assets/javascripts/pages/admin/application_settings/general/components/signup_form.vue
@@ -0,0 +1,331 @@
+<script>
+import {
+ GlButton,
+ GlFormGroup,
+ GlFormInput,
+ GlFormRadio,
+ GlFormRadioGroup,
+ GlSprintf,
+ GlLink,
+} from '@gitlab/ui';
+import csrf from '~/lib/utils/csrf';
+import { s__, sprintf } from '~/locale';
+import SignupCheckbox from './signup_checkbox.vue';
+
+const DENYLIST_TYPE_RAW = 'raw';
+const DENYLIST_TYPE_FILE = 'file';
+
+export default {
+ csrf,
+ DENYLIST_TYPE_RAW,
+ DENYLIST_TYPE_FILE,
+ components: {
+ GlButton,
+ GlFormGroup,
+ GlFormInput,
+ GlFormRadio,
+ GlFormRadioGroup,
+ GlSprintf,
+ GlLink,
+ SignupCheckbox,
+ },
+ inject: [
+ 'host',
+ 'settingsPath',
+ 'signupEnabled',
+ 'requireAdminApprovalAfterUserSignup',
+ 'sendUserConfirmationEmail',
+ 'minimumPasswordLength',
+ 'minimumPasswordLengthMin',
+ 'minimumPasswordLengthMax',
+ 'minimumPasswordLengthHelpLink',
+ 'domainAllowlistRaw',
+ 'newUserSignupsCap',
+ 'domainDenylistEnabled',
+ 'denylistTypeRawSelected',
+ 'domainDenylistRaw',
+ 'emailRestrictionsEnabled',
+ 'supportedSyntaxLinkUrl',
+ 'emailRestrictions',
+ 'afterSignUpText',
+ ],
+ data() {
+ return {
+ form: {
+ signupEnabled: this.signupEnabled,
+ requireAdminApproval: this.requireAdminApprovalAfterUserSignup,
+ sendConfirmationEmail: this.sendUserConfirmationEmail,
+ minimumPasswordLength: this.minimumPasswordLength,
+ minimumPasswordLengthMin: this.minimumPasswordLengthMin,
+ minimumPasswordLengthMax: this.minimumPasswordLengthMax,
+ minimumPasswordLengthHelpLink: this.minimumPasswordLengthHelpLink,
+ domainAllowlistRaw: this.domainAllowlistRaw,
+ userCap: this.newUserSignupsCap,
+ domainDenylistEnabled: this.domainDenylistEnabled,
+ denylistType: this.denylistTypeRawSelected
+ ? this.$options.DENYLIST_TYPE_RAW
+ : this.$options.DENYLIST_TYPE_FILE,
+ domainDenylistRaw: this.domainDenylistRaw,
+ emailRestrictionsEnabled: this.emailRestrictionsEnabled,
+ supportedSyntaxLinkUrl: this.supportedSyntaxLinkUrl,
+ emailRestrictions: this.emailRestrictions,
+ afterSignUpText: this.afterSignUpText,
+ },
+ };
+ },
+ computed: {
+ signupEnabledHelpText() {
+ const text = sprintf(
+ s__(
+ 'ApplicationSettings|When enabled, any user visiting %{host} will be able to create an account.',
+ ),
+ {
+ host: this.host,
+ },
+ );
+
+ return text;
+ },
+ requireAdminApprovalHelpText() {
+ const text = sprintf(
+ s__(
+ 'ApplicationSettings|When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by an admin before they can sign in. This setting is effective only if sign-ups are enabled.',
+ ),
+ {
+ host: this.host,
+ },
+ );
+
+ return text;
+ },
+ },
+ methods: {
+ submitButtonHandler() {
+ this.$refs.form.submit();
+ },
+ },
+ i18n: {
+ buttonText: s__('ApplicationSettings|Save changes'),
+ signupEnabledLabel: s__('ApplicationSettings|Sign-up enabled'),
+ requireAdminApprovalLabel: s__('ApplicationSettings|Require admin approval for new sign-ups'),
+ sendConfirmationEmailLabel: s__('ApplicationSettings|Send confirmation email on sign-up'),
+ minimumPasswordLengthLabel: s__(
+ 'ApplicationSettings|Minimum password length (number of characters)',
+ ),
+ domainAllowListLabel: s__('ApplicationSettings|Allowed domains for sign-ups'),
+ domainAllowListDescription: s__(
+ 'ApplicationSettings|ONLY users with e-mail addresses that match these domain(s) will be able to sign-up. Wildcards allowed. Use separate lines for multiple entries. Ex: domain.com, *.domain.com',
+ ),
+ userCapLabel: s__('ApplicationSettings|User cap'),
+ userCapDescription: s__(
+ 'ApplicationSettings|Once the instance reaches the user cap, any user who is added or requests access will have to be approved by an admin. Leave the field empty for unlimited.',
+ ),
+ domainDenyListGroupLabel: s__('ApplicationSettings|Domain denylist'),
+ domainDenyListLabel: s__('ApplicationSettings|Enable domain denylist for sign ups'),
+ domainDenyListTypeFileLabel: s__('ApplicationSettings|Upload denylist file'),
+ domainDenyListTypeRawLabel: s__('ApplicationSettings|Enter denylist manually'),
+ domainDenyListFileLabel: s__('ApplicationSettings|Denylist file'),
+ domainDenyListFileDescription: s__(
+ 'ApplicationSettings|Users with e-mail addresses that match these domain(s) will NOT be able to sign-up. Wildcards allowed. Use separate lines or commas for multiple entries.',
+ ),
+ domainDenyListListLabel: s__('ApplicationSettings|Denied domains for sign-ups'),
+ domainDenyListListDescription: s__(
+ 'ApplicationSettings|Users with e-mail addresses that match these domain(s) will NOT be able to sign-up. Wildcards allowed. Use separate lines for multiple entries. Ex: domain.com, *.domain.com',
+ ),
+ domainPlaceholder: s__('ApplicationSettings|domain.com'),
+ emailRestrictionsEnabledGroupLabel: s__('ApplicationSettings|Email restrictions'),
+ emailRestrictionsEnabledLabel: s__(
+ 'ApplicationSettings|Enable email restrictions for sign ups',
+ ),
+ emailRestrictionsGroupLabel: s__('ApplicationSettings|Email restrictions for sign-ups'),
+ afterSignUpTextGroupLabel: s__('ApplicationSettings|After sign up text'),
+ afterSignUpTextGroupDescription: s__('ApplicationSettings|Markdown enabled'),
+ },
+};
+</script>
+
+<template>
+ <form
+ ref="form"
+ accept-charset="UTF-8"
+ data-testid="form"
+ method="post"
+ :action="settingsPath"
+ enctype="multipart/form-data"
+ >
+ <input type="hidden" name="utf8" value="✓" />
+ <input type="hidden" name="_method" value="patch" />
+ <input type="hidden" name="authenticity_token" :value="$options.csrf.token" />
+
+ <section class="gl-mb-8">
+ <signup-checkbox
+ v-model="form.signupEnabled"
+ class="gl-mb-5"
+ name="application_setting[signup_enabled]"
+ :help-text="signupEnabledHelpText"
+ :label="$options.i18n.signupEnabledLabel"
+ data-qa-selector="signup_enabled_checkbox"
+ />
+
+ <signup-checkbox
+ v-model="form.requireAdminApproval"
+ class="gl-mb-5"
+ name="application_setting[require_admin_approval_after_user_signup]"
+ :help-text="requireAdminApprovalHelpText"
+ :label="$options.i18n.requireAdminApprovalLabel"
+ data-qa-selector="require_admin_approval_after_user_signup_checkbox"
+ />
+
+ <signup-checkbox
+ v-model="form.sendConfirmationEmail"
+ class="gl-mb-5"
+ name="application_setting[send_user_confirmation_email]"
+ :label="$options.i18n.sendConfirmationEmailLabel"
+ />
+
+ <gl-form-group
+ :label="$options.i18n.userCapLabel"
+ :description="$options.i18n.userCapDescription"
+ >
+ <gl-form-input
+ v-model="form.userCap"
+ type="text"
+ name="application_setting[new_user_signups_cap]"
+ />
+ </gl-form-group>
+
+ <gl-form-group :label="$options.i18n.minimumPasswordLengthLabel">
+ <gl-form-input
+ v-model="form.minimumPasswordLength"
+ :min="form.minimumPasswordLengthMin"
+ :max="form.minimumPasswordLengthMax"
+ type="number"
+ name="application_setting[minimum_password_length]"
+ />
+
+ <gl-sprintf
+ :message="
+ s__(
+ 'ApplicationSettings|See GitLab\'s %{linkStart}Password Policy Guidelines%{linkEnd}',
+ )
+ "
+ >
+ <template #link="{ content }">
+ <gl-link :href="form.minimumPasswordLengthHelpLink" target="_blank">{{
+ content
+ }}</gl-link>
+ </template>
+ </gl-sprintf>
+ </gl-form-group>
+
+ <gl-form-group
+ :description="$options.i18n.domainAllowListDescription"
+ :label="$options.i18n.domainAllowListLabel"
+ >
+ <textarea
+ v-model="form.domainAllowlistRaw"
+ :placeholder="$options.i18n.domainPlaceholder"
+ rows="8"
+ class="form-control gl-form-input"
+ name="application_setting[domain_allowlist_raw]"
+ ></textarea>
+ </gl-form-group>
+
+ <gl-form-group :label="$options.i18n.domainDenyListGroupLabel">
+ <signup-checkbox
+ v-model="form.domainDenylistEnabled"
+ name="application_setting[domain_denylist_enabled]"
+ :label="$options.i18n.domainDenyListLabel"
+ />
+ </gl-form-group>
+
+ <gl-form-radio-group v-model="form.denylistType" name="denylist_type" class="gl-mb-5">
+ <gl-form-radio :value="$options.DENYLIST_TYPE_FILE">{{
+ $options.i18n.domainDenyListTypeFileLabel
+ }}</gl-form-radio>
+ <gl-form-radio :value="$options.DENYLIST_TYPE_RAW">{{
+ $options.i18n.domainDenyListTypeRawLabel
+ }}</gl-form-radio>
+ </gl-form-radio-group>
+
+ <gl-form-group
+ v-if="form.denylistType === $options.DENYLIST_TYPE_FILE"
+ :description="$options.i18n.domainDenyListFileDescription"
+ :label="$options.i18n.domainDenyListFileLabel"
+ label-for="domain-denylist-file-input"
+ data-testid="domain-denylist-file-input-group"
+ >
+ <input
+ id="domain-denylist-file-input"
+ class="form-control gl-form-input"
+ type="file"
+ accept=".txt,.conf"
+ name="application_setting[domain_denylist_file]"
+ />
+ </gl-form-group>
+
+ <gl-form-group
+ v-if="form.denylistType !== $options.DENYLIST_TYPE_FILE"
+ :description="$options.i18n.domainDenyListListDescription"
+ :label="$options.i18n.domainDenyListListLabel"
+ data-testid="domain-denylist-raw-input-group"
+ >
+ <textarea
+ v-model="form.domainDenylistRaw"
+ :placeholder="$options.i18n.domainPlaceholder"
+ rows="8"
+ class="form-control gl-form-input"
+ name="application_setting[domain_denylist_raw]"
+ ></textarea>
+ </gl-form-group>
+
+ <gl-form-group :label="$options.i18n.emailRestrictionsEnabledGroupLabel">
+ <signup-checkbox
+ v-model="form.emailRestrictionsEnabled"
+ name="application_setting[email_restrictions_enabled]"
+ :label="$options.i18n.emailRestrictionsEnabledLabel"
+ />
+ </gl-form-group>
+
+ <gl-form-group :label="$options.i18n.emailRestrictionsGroupLabel">
+ <textarea
+ v-model="form.emailRestrictions"
+ rows="4"
+ class="form-control gl-form-input"
+ name="application_setting[email_restrictions]"
+ ></textarea>
+
+ <gl-sprintf
+ :message="
+ s__(
+ 'ApplicationSettings|Restricts sign-ups for email addresses that match the given regex. See the %{linkStart}supported syntax%{linkEnd} for more information.',
+ )
+ "
+ >
+ <template #link="{ content }">
+ <gl-link :href="form.supportedSyntaxLinkUrl" target="_blank">{{ content }}</gl-link>
+ </template>
+ </gl-sprintf>
+ </gl-form-group>
+
+ <gl-form-group
+ :label="$options.i18n.afterSignUpTextGroupLabel"
+ :description="$options.i18n.afterSignUpTextGroupDescription"
+ >
+ <textarea
+ v-model="form.afterSignUpText"
+ rows="4"
+ class="form-control gl-form-input"
+ name="application_setting[after_sign_up_text]"
+ ></textarea>
+ </gl-form-group>
+ </section>
+ <gl-button
+ data-qa-selector="save_changes_button"
+ variant="confirm"
+ @click="submitButtonHandler"
+ >
+ {{ $options.i18n.buttonText }}
+ </gl-button>
+ </form>
+</template>
diff --git a/app/assets/javascripts/pages/admin/application_settings/general/index.js b/app/assets/javascripts/pages/admin/application_settings/general/index.js
index eda1a9d3599..c48d99da990 100644
--- a/app/assets/javascripts/pages/admin/application_settings/general/index.js
+++ b/app/assets/javascripts/pages/admin/application_settings/general/index.js
@@ -1,27 +1,9 @@
-import Vue from 'vue';
-import IntegrationHelpText from '~/vue_shared/components/integrations_help_text.vue';
import initUserInternalRegexPlaceholder from '../account_and_limits';
+import initGitpod from '../gitpod';
+import initSignupRestrictions from '../signup_restrictions';
(() => {
initUserInternalRegexPlaceholder();
-
- const el = document.querySelector('#js-gitpod-settings-help-text');
- if (!el) {
- return;
- }
-
- const { message, messageUrl } = el.dataset;
-
- // eslint-disable-next-line no-new
- new Vue({
- el,
- render(createElement) {
- return createElement(IntegrationHelpText, {
- props: {
- message,
- messageUrl,
- },
- });
- },
- });
+ initGitpod();
+ initSignupRestrictions();
})();
diff --git a/app/assets/javascripts/pages/admin/application_settings/gitpod.js b/app/assets/javascripts/pages/admin/application_settings/gitpod.js
new file mode 100644
index 00000000000..74e46617d52
--- /dev/null
+++ b/app/assets/javascripts/pages/admin/application_settings/gitpod.js
@@ -0,0 +1,24 @@
+import Vue from 'vue';
+import IntegrationHelpText from '~/vue_shared/components/integrations_help_text.vue';
+
+export default function initGitpod() {
+ const el = document.querySelector('#js-gitpod-settings-help-text');
+
+ if (!el) {
+ return false;
+ }
+
+ const { message, messageUrl } = el.dataset;
+
+ return new Vue({
+ el,
+ render(createElement) {
+ return createElement(IntegrationHelpText, {
+ props: {
+ message,
+ messageUrl,
+ },
+ });
+ },
+ });
+}
diff --git a/app/assets/javascripts/pages/admin/application_settings/signup_restrictions.js b/app/assets/javascripts/pages/admin/application_settings/signup_restrictions.js
new file mode 100644
index 00000000000..70b896f6372
--- /dev/null
+++ b/app/assets/javascripts/pages/admin/application_settings/signup_restrictions.js
@@ -0,0 +1,31 @@
+import Vue from 'vue';
+import SignupForm from './general/components/signup_form.vue';
+import { getParsedDataset } from './utils';
+
+export default function initSignupRestrictions(elementSelector = '#js-signup-form') {
+ const el = document.querySelector(elementSelector);
+
+ if (!el) {
+ return false;
+ }
+
+ const parsedDataset = getParsedDataset({
+ dataset: el.dataset,
+ booleanAttributes: [
+ 'signupEnabled',
+ 'requireAdminApprovalAfterUserSignup',
+ 'sendUserConfirmationEmail',
+ 'domainDenylistEnabled',
+ 'denylistTypeRawSelected',
+ 'emailRestrictionsEnabled',
+ ],
+ });
+
+ return new Vue({
+ el,
+ provide: {
+ ...parsedDataset,
+ },
+ render: (createElement) => createElement(SignupForm),
+ });
+}
diff --git a/app/assets/javascripts/pages/admin/application_settings/utils.js b/app/assets/javascripts/pages/admin/application_settings/utils.js
new file mode 100644
index 00000000000..5462a13d523
--- /dev/null
+++ b/app/assets/javascripts/pages/admin/application_settings/utils.js
@@ -0,0 +1,21 @@
+import { includes } from 'lodash';
+import { parseBoolean } from '~/lib/utils/common_utils';
+
+/**
+ * Returns a new dataset that has all the values of keys indicated in
+ * booleanAttributes transformed by the parseBoolean() helper function
+ *
+ * @param {Object}
+ * @returns {Object}
+ */
+export const getParsedDataset = ({ dataset = {}, booleanAttributes = [] } = {}) => {
+ const parsedDataset = {};
+
+ Object.keys(dataset).forEach((key) => {
+ parsedDataset[key] = includes(booleanAttributes, key)
+ ? parseBoolean(dataset[key])
+ : dataset[key];
+ });
+
+ return parsedDataset;
+};
diff --git a/app/assets/javascripts/pages/projects/packages/infrastructure_registry/index/index.js b/app/assets/javascripts/pages/projects/packages/infrastructure_registry/index/index.js
index c94782fdf1b..dfb750eca41 100644
--- a/app/assets/javascripts/pages/projects/packages/infrastructure_registry/index/index.js
+++ b/app/assets/javascripts/pages/projects/packages/infrastructure_registry/index/index.js
@@ -1,3 +1,3 @@
-import initPackageList from '~/packages/list/packages_list_app_bundle';
+import initList from '~/packages_and_registries/infrastructure_registry/list_app_bundle';
-initPackageList();
+initList();
diff --git a/app/assets/stylesheets/pages/runners.scss b/app/assets/stylesheets/pages/runners.scss
index f684cb090e2..d01c9a9fd42 100644
--- a/app/assets/stylesheets/pages/runners.scss
+++ b/app/assets/stylesheets/pages/runners.scss
@@ -11,17 +11,3 @@
background: $blue-400;
}
}
-
-.runner-status {
- &.runner-status-online {
- background-color: $green-600;
- }
-
- &.runner-status-offline {
- background-color: $gray-darkest;
- }
-
- &.runner-status-paused {
- background-color: $red-500;
- }
-}
diff --git a/app/helpers/ci/runners_helper.rb b/app/helpers/ci/runners_helper.rb
index ba5d4e8c65a..82347053d6f 100644
--- a/app/helpers/ci/runners_helper.rb
+++ b/app/helpers/ci/runners_helper.rb
@@ -4,18 +4,33 @@ module Ci
module RunnersHelper
include IconsHelper
- def runner_status_icon(runner)
+ def runner_status_icon(runner, size: 16, icon_class: '')
status = runner.status
+
+ title = ''
+ icon = 'warning-solid'
+ span_class = ''
+
case status
when :not_connected
- content_tag(:span, title: _("New runner. Has not connected yet")) do
- sprite_icon("warning-solid", size: 24, css_class: "gl-vertical-align-bottom!")
- end
+ title = s_("Runners|New runner, has not connected yet")
+ icon = 'warning-solid'
+ when :online
+ title = s_("Runners|Runner is online, last contact was %{runner_contact} ago") % { runner_contact: time_ago_in_words(runner.contacted_at) }
+ icon = 'status-active'
+ span_class = 'gl-text-green-500'
+ when :offline
+ title = s_("Runners|Runner is offline, last contact was %{runner_contact} ago") % { runner_contact: time_ago_in_words(runner.contacted_at) }
+ icon = 'status-failed'
+ span_class = 'gl-text-red-500'
+ when :paused
+ title = s_("Runners|Runner is paused, last contact was %{runner_contact} ago") % { runner_contact: time_ago_in_words(runner.contacted_at) }
+ icon = 'status-paused'
+ span_class = 'gl-text-gray-600'
+ end
- when :online, :offline, :paused
- content_tag :span, nil,
- class: "gl-display-inline-block gl-avatar gl-avatar-s16 gl-avatar-circle runner-status runner-status-#{status}",
- title: _("Runner is %{status}, last contact was %{runner_contact} ago") % { status: status, runner_contact: time_ago_in_words(runner.contacted_at) }
+ content_tag(:span, class: span_class, title: title, data: { toggle: 'tooltip', container: 'body', testid: 'runner_status_icon', qa_selector: "runner_status_#{status}_content" }) do
+ sprite_icon(icon, size: size, css_class: icon_class)
end
end
diff --git a/app/models/namespaces/traversal/recursive.rb b/app/models/namespaces/traversal/recursive.rb
index aac70a1a0a9..409438f53d2 100644
--- a/app/models/namespaces/traversal/recursive.rb
+++ b/app/models/namespaces/traversal/recursive.rb
@@ -22,6 +22,7 @@ module Namespaces
object_hierarchy(self.class.where(id: id))
.all_objects
end
+ alias_method :recursive_self_and_hierarchy, :self_and_hierarchy
# Returns all the ancestors of the current namespaces.
def ancestors
@@ -30,6 +31,7 @@ module Namespaces
object_hierarchy(self.class.where(id: parent_id))
.base_and_ancestors
end
+ alias_method :recursive_ancestors, :ancestors
# returns all ancestors upto but excluding the given namespace
# when no namespace is given, all ancestors upto the top are returned
@@ -44,17 +46,20 @@ module Namespaces
object_hierarchy(self.class.where(id: id))
.base_and_ancestors(hierarchy_order: hierarchy_order)
end
+ alias_method :recursive_self_and_ancestors, :self_and_ancestors
# Returns all the descendants of the current namespace.
def descendants
object_hierarchy(self.class.where(parent_id: id))
.base_and_descendants
end
+ alias_method :recursive_descendants, :descendants
def self_and_descendants
object_hierarchy(self.class.where(id: id))
.base_and_descendants
end
+ alias_method :recursive_self_and_descendants, :self_and_descendants
def object_hierarchy(ancestors_base)
Gitlab::ObjectHierarchy.new(ancestors_base, options: { use_distinct: Feature.enabled?(:use_distinct_in_object_hierarchy, self) })
diff --git a/app/views/admin/application_settings/_signup.html.haml b/app/views/admin/application_settings/_signup.html.haml
index 272eba67b1b..a5b47159239 100644
--- a/app/views/admin/application_settings/_signup.html.haml
+++ b/app/views/admin/application_settings/_signup.html.haml
@@ -1,80 +1,20 @@
-= form_for @application_setting, url: general_admin_application_settings_path(anchor: 'js-signup-settings'), html: { class: 'fieldset-form' } do |f|
- = form_errors(@application_setting)
+= form_errors(@application_setting)
- %fieldset
- .form-group
- .form-check
- = f.check_box :signup_enabled, class: 'form-check-input', data: { qa_selector: 'signup_enabled_checkbox' }
- = f.label :signup_enabled, class: 'form-check-label' do
- Sign-up enabled
- .form-text.text-muted
- = _("When enabled, any user visiting %{host} will be able to create an account.") % { host: "#{new_user_session_url(host: Gitlab.config.gitlab.host)}" }
- .form-group
- .form-check
- = f.check_box :require_admin_approval_after_user_signup, class: 'form-check-input', data: { qa_selector: 'require_admin_approval_after_user_signup_checkbox' }
- = f.label :require_admin_approval_after_user_signup, class: 'form-check-label' do
- = _('Require admin approval for new sign-ups')
- .form-text.text-muted
- = _("When enabled, any user visiting %{host} and creating an account will have to be explicitly approved by an admin before they can sign in. This setting is effective only if sign-ups are enabled.") % { host: "#{new_user_session_url(host: Gitlab.config.gitlab.host)}" }
- .form-group
- .form-check
- = f.check_box :send_user_confirmation_email, class: 'form-check-input'
- = f.label :send_user_confirmation_email, class: 'form-check-label' do
- Send confirmation email on sign-up
-
- = render_if_exists 'admin/application_settings/new_user_signups_cap', form: f
-
- .form-group
- = f.label :minimum_password_length, _('Minimum password length (number of characters)'), class: 'label-bold'
- = f.number_field :minimum_password_length, class: 'form-control gl-form-input', rows: 4, min: ApplicationSetting::DEFAULT_MINIMUM_PASSWORD_LENGTH, max: Devise.password_length.max
- - password_policy_guidelines_link = link_to _('Password Policy Guidelines'), 'https://about.gitlab.com/handbook/security/#gitlab-password-policy-guidelines', target: '_blank', rel: 'noopener noreferrer nofollow'
- .form-text.text-muted
- = _("See GitLab's %{password_policy_guidelines}").html_safe % { password_policy_guidelines: password_policy_guidelines_link }
- .form-group
- = f.label :domain_allowlist, _('Allowed domains for sign-ups'), class: 'label-bold'
- = f.text_area :domain_allowlist_raw, placeholder: 'domain.com', class: 'form-control gl-form-input', rows: 8
- .form-text.text-muted ONLY users with e-mail addresses that match these domain(s) will be able to sign-up. Wildcards allowed. Use separate lines for multiple entries. Ex: domain.com, *.domain.com
- .form-group
- = f.label :domain_denylist_enabled, _('Domain denylist'), class: 'label-bold'
- .form-check
- = f.check_box :domain_denylist_enabled, class: 'form-check-input'
- = f.label :domain_denylist_enabled, class: 'form-check-label' do
- Enable domain denylist for sign ups
- .form-group
- .form-check
- = radio_button_tag :denylist_type, :file, false, class: 'form-check-input'
- = label_tag :denylist_type_file, class: 'form-check-label' do
- .option-title
- Upload denylist file
- .form-check
- = radio_button_tag :denylist_type, :raw, @application_setting.domain_denylist.present? || @application_setting.domain_denylist.blank?, class: 'form-check-input'
- = label_tag :denylist_type_raw, class: 'form-check-label' do
- .option-title
- Enter denylist manually
- .form-group.js-denylist-file
- = f.label :domain_denylist_file, _('Denylist file'), class: 'label-bold'
- = f.file_field :domain_denylist_file, class: 'form-control gl-form-input', accept: '.txt,.conf'
- .form-text.text-muted Users with e-mail addresses that match these domain(s) will NOT be able to sign-up. Wildcards allowed. Use separate lines or commas for multiple entries.
- .form-group.js-denylist-raw
- = f.label :domain_denylist, _('Denied domains for sign-ups'), class: 'label-bold'
- = f.text_area :domain_denylist_raw, placeholder: 'domain.com', class: 'form-control gl-form-input', rows: 8
- .form-text.text-muted Users with e-mail addresses that match these domain(s) will NOT be able to sign-up. Wildcards allowed. Use separate lines for multiple entries. Ex: domain.com, *.domain.com
- .form-group
- = f.label :email_restrictions_enabled, _('Email restrictions'), class: 'label-bold'
- .form-check
- = f.check_box :email_restrictions_enabled, class: 'form-check-input'
- = f.label :email_restrictions_enabled, class: 'form-check-label' do
- = _('Enable email restrictions for sign ups')
- .form-group
- = f.label :email_restrictions, _('Email restrictions for sign-ups'), class: 'label-bold'
- = f.text_area :email_restrictions, class: 'form-control gl-form-input', rows: 4
- .form-text.text-muted
- - supported_syntax_link_url = 'https://github.com/google/re2/wiki/Syntax'
- - supported_syntax_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: supported_syntax_link_url }
- = _('Restricts sign-ups for email addresses that match the given regex. See the %{supported_syntax_link_start}supported syntax%{supported_syntax_link_end} for more information.').html_safe % { supported_syntax_link_start: supported_syntax_link_start, supported_syntax_link_end: '</a>'.html_safe }
-
- .form-group
- = f.label :after_sign_up_text, class: 'label-bold'
- = f.text_area :after_sign_up_text, class: 'form-control gl-form-input', rows: 4
- .form-text.text-muted Markdown enabled
- = f.submit 'Save changes', class: "gl-button btn btn-confirm", data: { qa_selector: 'save_changes_button' }
+#js-signup-form{ data: { host: new_user_session_url(host: Gitlab.config.gitlab.host),
+ settings_path: general_admin_application_settings_path(anchor: 'js-signup-settings'),
+ signup_enabled: @application_setting[:signup_enabled].to_s,
+ require_admin_approval_after_user_signup: @application_setting[:require_admin_approval_after_user_signup].to_s,
+ send_user_confirmation_email: @application_setting[:send_user_confirmation_email].to_s,
+ minimum_password_length: @application_setting[:minimum_password_length],
+ minimum_password_length_min: ApplicationSetting::DEFAULT_MINIMUM_PASSWORD_LENGTH,
+ minimum_password_length_max: Devise.password_length.max,
+ minimum_password_length_help_link: 'https://about.gitlab.com/handbook/security/#gitlab-password-policy-guidelines',
+ domain_allowlist_raw: @application_setting.domain_allowlist_raw,
+ new_user_signups_cap: @application_setting[:new_user_signups_cap].to_s,
+ domain_denylist_enabled: @application_setting[:domain_denylist_enabled].to_s,
+ denylist_type_raw_selected: (@application_setting.domain_denylist.present? || @application_setting.domain_denylist.blank?).to_s,
+ domain_denylist_raw: @application_setting.domain_denylist_raw,
+ email_restrictions_enabled: @application_setting[:email_restrictions_enabled].to_s,
+ supported_syntax_link_url: 'https://github.com/google/re2/wiki/Syntax',
+ email_restrictions: @application_setting.email_restrictions,
+ after_sign_up_text: @application_setting[:after_sign_up_text] } }
diff --git a/app/views/projects/packages/infrastructure_registry/index.html.haml b/app/views/projects/packages/infrastructure_registry/index.html.haml
index e8be9051275..5a118997ff9 100644
--- a/app/views/projects/packages/infrastructure_registry/index.html.haml
+++ b/app/views/projects/packages/infrastructure_registry/index.html.haml
@@ -5,6 +5,6 @@
.col-12
#js-vue-packages-list{ data: { resource_id: @project.id,
page_type: 'project',
- empty_list_help_url: help_page_path('user/packages/package_registry/index'),
- empty_list_illustration: image_path('illustrations/no-packages.svg'),
- package_help_url: help_page_path('user/packages/index') } }
+ empty_list_help_url: help_page_path('user/infrastructure/index'),
+ empty_list_illustration: image_path('illustrations/empty-state/empty-terraform-register-lg.svg'),
+ package_help_url: help_page_path('user/infrastructure/index') } }
diff --git a/app/views/projects/runners/_runner.html.haml b/app/views/projects/runners/_runner.html.haml
index 0d67deb34cf..bc043a5f394 100644
--- a/app/views/projects/runners/_runner.html.haml
+++ b/app/views/projects/runners/_runner.html.haml
@@ -1,6 +1,6 @@
%li.runner{ id: dom_id(runner) }
%h4.gl-font-weight-normal
- = runner_status_icon(runner)
+ = runner_status_icon(runner, size: 16, icon_class: "gl-vertical-align-middle!")
- if @project_runners.include?(runner)
= link_to _("%{token}...") % { token: runner.short_sha }, project_runner_path(@project, runner), class: 'commit-sha has-tooltip', title: _("Partial token for reference only")
diff --git a/app/workers/all_queues.yml b/app/workers/all_queues.yml
index 2f2fd19a3aa..ef7b5eb026e 100644
--- a/app/workers/all_queues.yml
+++ b/app/workers/all_queues.yml
@@ -2377,7 +2377,7 @@
:idempotent:
:tags: []
- :name: update_highest_role
- :feature_category: :authentication_and_authorization
+ :feature_category: :utilization
:has_external_dependencies:
:urgency: :high
:resource_boundary: :unknown
diff --git a/app/workers/update_highest_role_worker.rb b/app/workers/update_highest_role_worker.rb
index 1e2c974b6e5..952f1e511ea 100644
--- a/app/workers/update_highest_role_worker.rb
+++ b/app/workers/update_highest_role_worker.rb
@@ -3,7 +3,7 @@
class UpdateHighestRoleWorker
include ApplicationWorker
- feature_category :authentication_and_authorization
+ feature_category :utilization
urgency :high
weight 2