+
+
+
+
+ {{ caption }}
+
+
+
+
diff --git a/app/assets/javascripts/behaviors/markdown/render_gfm.js b/app/assets/javascripts/behaviors/markdown/render_gfm.js
index c9ae3706383..ee5c0fe5ef3 100644
--- a/app/assets/javascripts/behaviors/markdown/render_gfm.js
+++ b/app/assets/javascripts/behaviors/markdown/render_gfm.js
@@ -5,6 +5,7 @@ import { renderKroki } from './render_kroki';
import renderMath from './render_math';
import renderSandboxedMermaid from './render_sandboxed_mermaid';
import renderMetrics from './render_metrics';
+import { renderJSONTable } from './render_json_table';
// Render GitLab flavoured Markdown
//
@@ -15,6 +16,9 @@ $.fn.renderGFM = function renderGFM() {
renderKroki(this.find('.js-render-kroki[hidden]').get());
renderMath(this.find('.js-render-math'));
renderSandboxedMermaid(this.find('.js-render-mermaid'));
+ renderJSONTable(
+ Array.from(this.find('[lang="json"][data-lang-params="table"]').get()).map((e) => e.parentNode),
+ );
highlightCurrentUser(this.find('.gfm-project_member').get());
diff --git a/app/assets/javascripts/behaviors/markdown/render_json_table.js b/app/assets/javascripts/behaviors/markdown/render_json_table.js
new file mode 100644
index 00000000000..4d9ac1d266b
--- /dev/null
+++ b/app/assets/javascripts/behaviors/markdown/render_json_table.js
@@ -0,0 +1,70 @@
+import { memoize } from 'lodash';
+import Vue from 'vue';
+import { __ } from '~/locale';
+import { createAlert } from '~/flash';
+
+// Async import component since we might not need it...
+const JSONTable = memoize(() =>
+ import(/* webpackChunkName: 'gfm_json_table' */ '../components/json_table.vue'),
+);
+
+const mountParseError = (element) => {
+ // Let the error container be a sibling to the element.
+ // Otherwise, dismissing the alert causes the copy button to be misplaced.
+ const container = document.createElement('div');
+ element.insertAdjacentElement('beforebegin', container);
+
+ // We need to create a child element with a known selector for `createAlert`
+ const el = document.createElement('div');
+ el.classList.add('js-json-table-error');
+
+ container.insertAdjacentElement('afterbegin', el);
+
+ return createAlert({
+ message: __('Unable to parse JSON'),
+ variant: 'warning',
+ parent: container,
+ containerSelector: '.js-json-table-error',
+ });
+};
+
+const mountJSONTableVueComponent = (userData, element) => {
+ const { fields = [], items = [], filter, caption } = userData;
+
+ const container = document.createElement('div');
+ element.innerHTML = '';
+ element.appendChild(container);
+
+ return new Vue({
+ el: container,
+ render(h) {
+ return h(JSONTable, {
+ props: {
+ fields,
+ items,
+ hasFilter: filter,
+ caption,
+ },
+ });
+ },
+ });
+};
+
+const renderTable = (element) => {
+ // Avoid rendering multiple times
+ if (!element || element.classList.contains('js-json-table')) {
+ return;
+ }
+
+ element.classList.add('js-json-table');
+
+ try {
+ mountJSONTableVueComponent(JSON.parse(element.textContent), element);
+ } catch (e) {
+ mountParseError(element);
+ }
+};
+
+export const renderJSONTable = (elements) => {
+ elements.forEach(renderTable);
+};
diff --git a/db/migrate/20220718083945_add_unique_project_download_limit_allowlist_to_namespace_settings.rb b/db/migrate/20220718083945_add_unique_project_download_limit_allowlist_to_namespace_settings.rb
new file mode 100644
index 00000000000..49d9a652472
--- /dev/null
+++ b/db/migrate/20220718083945_add_unique_project_download_limit_allowlist_to_namespace_settings.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+class AddUniqueProjectDownloadLimitAllowlistToNamespaceSettings < Gitlab::Database::Migration[2.0]
+ def change
+ add_column :namespace_settings, :unique_project_download_limit_allowlist,
+ :text,
+ array: true,
+ default: [],
+ null: false
+ end
+end
diff --git a/db/migrate/20220726025516_add_namespace_settings_unique_project_download_limit_allowlist_size_constraint.rb b/db/migrate/20220726025516_add_namespace_settings_unique_project_download_limit_allowlist_size_constraint.rb
new file mode 100644
index 00000000000..bded83f7941
--- /dev/null
+++ b/db/migrate/20220726025516_add_namespace_settings_unique_project_download_limit_allowlist_size_constraint.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class AddNamespaceSettingsUniqueProjectDownloadLimitAllowlistSizeConstraint < Gitlab::Database::Migration[2.0]
+ CONSTRAINT_NAME = 'namespace_settings_unique_project_download_limit_allowlist_size'
+
+ disable_ddl_transaction!
+
+ def up
+ add_check_constraint :namespace_settings,
+ 'CARDINALITY(unique_project_download_limit_allowlist) <= 100',
+ CONSTRAINT_NAME
+ end
+
+ def down
+ remove_check_constraint :namespace_settings, CONSTRAINT_NAME
+ end
+end
diff --git a/db/schema_migrations/20220718083945 b/db/schema_migrations/20220718083945
new file mode 100644
index 00000000000..f1d247e5349
--- /dev/null
+++ b/db/schema_migrations/20220718083945
@@ -0,0 +1 @@
+42b601de66244f527b8c40182b7c9c8ba3a6ea9863582be3c499ffe2491c8d4f
\ No newline at end of file
diff --git a/db/schema_migrations/20220726025516 b/db/schema_migrations/20220726025516
new file mode 100644
index 00000000000..58bab5467db
--- /dev/null
+++ b/db/schema_migrations/20220726025516
@@ -0,0 +1 @@
+326acd1c7e562056d29d5727869a0d0e5a5e9c387b0f54238c79c89f3947808b
\ No newline at end of file
diff --git a/db/structure.sql b/db/structure.sql
index 301b5b50871..ff56ae202e8 100644
--- a/db/structure.sql
+++ b/db/structure.sql
@@ -17613,7 +17613,9 @@ CREATE TABLE namespace_settings (
unique_project_download_limit_interval_in_seconds integer DEFAULT 0 NOT NULL,
project_import_level smallint DEFAULT 50 NOT NULL,
include_for_free_user_cap_preview boolean DEFAULT false NOT NULL,
- CONSTRAINT check_0ba93c78c7 CHECK ((char_length(default_branch_name) <= 255))
+ unique_project_download_limit_allowlist text[] DEFAULT '{}'::text[] NOT NULL,
+ CONSTRAINT check_0ba93c78c7 CHECK ((char_length(default_branch_name) <= 255)),
+ CONSTRAINT namespace_settings_unique_project_download_limit_allowlist_size CHECK ((cardinality(unique_project_download_limit_allowlist) <= 100))
);
CREATE TABLE namespace_statistics (
diff --git a/doc/administration/index.md b/doc/administration/index.md
index e618ce5f3bf..d5f59692173 100644
--- a/doc/administration/index.md
+++ b/doc/administration/index.md
@@ -241,4 +241,4 @@ who are aware of the risks.
- [Testing with OpenSSL](https://www.feistyduck.com/library/openssl-cookbook/online/testing-with-openssl/index.html)
- [`strace` zine](https://wizardzines.com/zines/strace/)
- GitLab.com-specific resources:
- - [Group SAML/SCIM setup](troubleshooting/group_saml_scim.md)
+ - [Example group SAML and SCIM configurations](../user/group/saml_sso/example_saml_config.md)
diff --git a/doc/administration/troubleshooting/group_saml_scim.md b/doc/administration/troubleshooting/group_saml_scim.md
index 145eb5f65ae..b5187504231 100644
--- a/doc/administration/troubleshooting/group_saml_scim.md
+++ b/doc/administration/troubleshooting/group_saml_scim.md
@@ -1,207 +1,11 @@
---
-stage: Manage
-group: Authentication and Authorization
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
-type: reference
+redirect_to: '../../user/group/saml_sso/example_saml_config.md'
+remove_date: '2022-10-29'
---
-# Troubleshooting Group SAML and SCIM **(PREMIUM SAAS)**
+This document was moved to [another location](../../user/group/saml_sso/example_saml_config.md).
-These are notes and screenshots regarding Group SAML and SCIM that the GitLab Support Team sometimes uses while troubleshooting, but which do not fit into the official documentation. GitLab is making this public, so that anyone can make use of the Support team's collected knowledge.
-
-Please refer to the GitLab [Group SAML](../../user/group/saml_sso/index.md) docs for information on the feature and how to set it up.
-
-When troubleshooting a SAML configuration, GitLab team members will frequently start with the [SAML troubleshooting section](../../user/group/saml_sso/index.md#troubleshooting).
-
-They may then set up a test configuration of the desired identity provider. We include example screenshots in this section.
-
-## SAML and SCIM screenshots
-
-This section includes relevant screenshots of the following example configurations of [Group SAML](../../user/group/saml_sso/index.md) and [Group SCIM](../../user/group/saml_sso/scim_setup.md):
-
-- [Azure Active Directory](#azure-active-directory)
-- [Google Workspace](#google-workspace)
-- [Okta](#okta)
-- [OneLogin](#onelogin)
-
-WARNING:
-These screenshots are updated only as needed by GitLab Support. They are **not** official documentation.
-
-If you are currently having an issue with GitLab, you may want to check your [support options](https://about.gitlab.com/support/).
-
-## Azure Active Directory
-
-Basic SAML app configuration:
-
-
-
-User claims and attributes:
-
-
-
-SCIM mapping:
-
-
-
-
-Group Sync:
-
-
-
-## Google Workspace
-
-Basic SAML app configuration:
-
-
-
-User claims and attributes:
-
-
-
-IdP links and certificate:
-
-NOTE:
-Google Workspace displays a SHA256 fingerprint. To retrieve the SHA1 fingerprint required by GitLab for configuring SAML, download the certificate and calculate the SHA1 certificate
-fingerprint.
-
-
-
-## Okta
-
-Basic SAML app configuration:
-
-
-
-User claims and attributes:
-
-
-
-Advanced SAML app settings (defaults):
-
-
-
-IdP Links and Certificate:
-
-
-
-Sign on settings:
-
-
-
-Self-managed instance example:
-
-
-
-Setting the username for the newly provisioned users when assigning them the SCIM app:
-
-
-
-## OneLogin
-
-Application details:
-
-
-
-Parameters:
-
-
-
-Adding a user:
-
-
-
-SSO settings:
-
-
-
-## SAML response example
-
-When a user signs in using SAML, GitLab receives a SAML response. The SAML response can be found in `production.log` logs as a base64-encoded message. Locate the response by
-searching for `SAMLResponse`. The decoded SAML response is in XML format. For example:
-
-```xml
-
-