diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2019-11-07 06:06:12 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2019-11-07 06:06:12 +0000 |
commit | 2a87ae2e368ec6fbb1e75b89bc092ba2fd7eb913 (patch) | |
tree | 4d6b995e3292562627ddeeacbc5b5eba0ce64032 | |
parent | eb0d9e20c5a81b0a556308ae3fc8015fcc3c9621 (diff) | |
download | gitlab-ce-2a87ae2e368ec6fbb1e75b89bc092ba2fd7eb913.tar.gz |
Add latest changes from gitlab-org/gitlab@master
26 files changed, 152 insertions, 44 deletions
diff --git a/app/assets/javascripts/grafana_integration/components/grafana_integration.vue b/app/assets/javascripts/grafana_integration/components/grafana_integration.vue index 2d3212429db..35135792c5b 100644 --- a/app/assets/javascripts/grafana_integration/components/grafana_integration.vue +++ b/app/assets/javascripts/grafana_integration/components/grafana_integration.vue @@ -1,11 +1,12 @@ <script> -import { GlButton, GlFormGroup, GlFormInput, GlLink } from '@gitlab/ui'; +import { GlButton, GlFormGroup, GlFormInput, GlFormCheckbox, GlLink } from '@gitlab/ui'; import Icon from '~/vue_shared/components/icon.vue'; import { mapState, mapActions } from 'vuex'; export default { components: { GlButton, + GlFormCheckbox, GlFormGroup, GlFormInput, GlLink, @@ -15,7 +16,15 @@ export default { return { placeholderUrl: 'https://my-url.grafana.net/my-dashboard' }; }, computed: { - ...mapState(['operationsSettingsEndpoint', 'grafanaToken', 'grafanaUrl']), + ...mapState(['operationsSettingsEndpoint', 'grafanaToken', 'grafanaUrl', 'grafanaEnabled']), + integrationEnabled: { + get() { + return this.grafanaEnabled; + }, + set(grafanaEnabled) { + this.setGrafanaEnabled(grafanaEnabled); + }, + }, localGrafanaToken: { get() { return this.grafanaToken; @@ -34,7 +43,12 @@ export default { }, }, methods: { - ...mapActions(['setGrafanaUrl', 'setGrafanaToken', 'updateGrafanaIntegration']), + ...mapActions([ + 'setGrafanaUrl', + 'setGrafanaToken', + 'setGrafanaEnabled', + 'updateGrafanaIntegration', + ]), }, }; </script> @@ -52,6 +66,13 @@ export default { </div> <div class="settings-content"> <form> + <gl-form-checkbox + id="grafana-integration-enabled" + v-model="integrationEnabled" + class="mb-4" + > + {{ s__('GrafanaIntegration|Active') }} + </gl-form-checkbox> <gl-form-group :label="s__('GrafanaIntegration|Grafana URL')" label-for="grafana-url" diff --git a/app/assets/javascripts/grafana_integration/index.js b/app/assets/javascripts/grafana_integration/index.js index 58c28e09f80..a93edab4388 100644 --- a/app/assets/javascripts/grafana_integration/index.js +++ b/app/assets/javascripts/grafana_integration/index.js @@ -4,7 +4,6 @@ import GrafanaIntegration from './components/grafana_integration.vue'; export default () => { const el = document.querySelector('.js-grafana-integration'); - return new Vue({ el, store: store(el.dataset), diff --git a/app/assets/javascripts/grafana_integration/store/actions.js b/app/assets/javascripts/grafana_integration/store/actions.js index 98085fdcb2d..d83f1e0831c 100644 --- a/app/assets/javascripts/grafana_integration/store/actions.js +++ b/app/assets/javascripts/grafana_integration/store/actions.js @@ -9,6 +9,9 @@ export const setGrafanaUrl = ({ commit }, url) => commit(mutationTypes.SET_GRAFA export const setGrafanaToken = ({ commit }, token) => commit(mutationTypes.SET_GRAFANA_TOKEN, token); +export const setGrafanaEnabled = ({ commit }, enabled) => + commit(mutationTypes.SET_GRAFANA_ENABLED, enabled); + export const updateGrafanaIntegration = ({ state, dispatch }) => axios .patch(state.operationsSettingsEndpoint, { @@ -16,6 +19,7 @@ export const updateGrafanaIntegration = ({ state, dispatch }) => grafana_integration_attributes: { grafana_url: state.grafanaUrl, token: state.grafanaToken, + enabled: state.grafanaEnabled, }, }, }) diff --git a/app/assets/javascripts/grafana_integration/store/mutation_types.js b/app/assets/javascripts/grafana_integration/store/mutation_types.js index 33ce3228823..314c3a4039a 100644 --- a/app/assets/javascripts/grafana_integration/store/mutation_types.js +++ b/app/assets/javascripts/grafana_integration/store/mutation_types.js @@ -1,2 +1,3 @@ export const SET_GRAFANA_URL = 'SET_GRAFANA_URL'; export const SET_GRAFANA_TOKEN = 'SET_GRAFANA_TOKEN'; +export const SET_GRAFANA_ENABLED = 'SET_GRAFANA_ENABLED'; diff --git a/app/assets/javascripts/grafana_integration/store/mutations.js b/app/assets/javascripts/grafana_integration/store/mutations.js index e8d63a9a732..0992030d404 100644 --- a/app/assets/javascripts/grafana_integration/store/mutations.js +++ b/app/assets/javascripts/grafana_integration/store/mutations.js @@ -7,4 +7,7 @@ export default { [types.SET_GRAFANA_TOKEN](state, token) { state.grafanaToken = token; }, + [types.SET_GRAFANA_ENABLED](state, enabled) { + state.grafanaEnabled = enabled; + }, }; diff --git a/app/assets/javascripts/grafana_integration/store/state.js b/app/assets/javascripts/grafana_integration/store/state.js index c25742c82bc..a912eb58327 100644 --- a/app/assets/javascripts/grafana_integration/store/state.js +++ b/app/assets/javascripts/grafana_integration/store/state.js @@ -1,5 +1,8 @@ +import { parseBoolean } from '~/lib/utils/common_utils'; + export default (initialState = {}) => ({ operationsSettingsEndpoint: initialState.operationsSettingsEndpoint, grafanaToken: initialState.grafanaIntegrationToken || '', grafanaUrl: initialState.grafanaIntegrationUrl || '', + grafanaEnabled: parseBoolean(initialState.grafanaIntegrationEnabled) || false, }); diff --git a/app/assets/javascripts/reports/components/issue_status_icon.vue b/app/assets/javascripts/reports/components/issue_status_icon.vue index 386653b9444..62a9338b864 100644 --- a/app/assets/javascripts/reports/components/issue_status_icon.vue +++ b/app/assets/javascripts/reports/components/issue_status_icon.vue @@ -50,6 +50,6 @@ export default { }" class="report-block-list-icon" > - <icon :name="iconName" :size="statusIconSize" /> + <icon :name="iconName" :size="statusIconSize" :data-qa-selector="`status_${status}_icon`" /> </div> </template> diff --git a/app/assets/javascripts/reports/components/report_item.vue b/app/assets/javascripts/reports/components/report_item.vue index f3f7d2648a8..3c8a9e6ebef 100644 --- a/app/assets/javascripts/reports/components/report_item.vue +++ b/app/assets/javascripts/reports/components/report_item.vue @@ -46,6 +46,7 @@ export default { <li :class="{ 'is-dismissed': issue.isDismissed }" class="report-block-list-issue align-items-center" + data-qa-selector="report_item_row" > <issue-status-icon v-if="showReportSectionStatusIcon" diff --git a/app/assets/stylesheets/utilities.scss b/app/assets/stylesheets/utilities.scss index 4a0b6ac1ddd..f53b6fbb1e7 100644 --- a/app/assets/stylesheets/utilities.scss +++ b/app/assets/stylesheets/utilities.scss @@ -27,3 +27,4 @@ .border-style-solid { border-style: solid; } .border-color-blue-300 { border-color: $blue-300; } .border-color-default { border-color: $border-color; } +.box-shadow-default { box-shadow: 0 2px 4px 0 $black-transparent; } diff --git a/app/policies/personal_snippet_policy.rb b/app/policies/personal_snippet_policy.rb index 67c66e42d79..91a8f3a7133 100644 --- a/app/policies/personal_snippet_policy.rb +++ b/app/policies/personal_snippet_policy.rb @@ -10,7 +10,7 @@ class PersonalSnippetPolicy < BasePolicy enable :create_note end - rule { is_author }.policy do + rule { is_author | admin }.policy do enable :read_personal_snippet enable :update_personal_snippet enable :destroy_personal_snippet diff --git a/app/views/projects/settings/operations/_grafana_integration.html.haml b/app/views/projects/settings/operations/_grafana_integration.html.haml index ae90b6dd5aa..cd5b5abd9ce 100644 --- a/app/views/projects/settings/operations/_grafana_integration.html.haml +++ b/app/views/projects/settings/operations/_grafana_integration.html.haml @@ -1,2 +1,2 @@ .js-grafana-integration{ data: { operations_settings_endpoint: project_settings_operations_path(@project), - grafana_integration: { url: grafana_integration_url, token: grafana_integration_token } } } + grafana_integration: { url: grafana_integration_url, token: grafana_integration_token, enabled: grafana_integration_enabled?.to_s } } } diff --git a/app/views/shared/projects/_list.html.haml b/app/views/shared/projects/_list.html.haml index d70a1631010..59b4facdbe5 100644 --- a/app/views/shared/projects/_list.html.haml +++ b/app/views/shared/projects/_list.html.haml @@ -32,7 +32,7 @@ - explore_groups_button_label = _('Explore groups') - explore_groups_button_link = explore_groups_path -.js-projects-list-holder +.js-projects-list-holder{ data: { qa_selector: 'projects_list' } } - if any_projects?(projects) - load_pipeline_status(projects) if pipeline_status %ul.projects-list{ class: css_classes } diff --git a/changelogs/unreleased/26380-personal-snippets.yml b/changelogs/unreleased/26380-personal-snippets.yml new file mode 100644 index 00000000000..6ea38a4623c --- /dev/null +++ b/changelogs/unreleased/26380-personal-snippets.yml @@ -0,0 +1,5 @@ +--- +title: Allow admins to administer personal snippets +merge_request: 19693 +author: Oren Kanner +type: fixed diff --git a/changelogs/unreleased/32419-growth-conversion-experiment-test-new-admin-upgrade-design-copy-for.yml b/changelogs/unreleased/32419-growth-conversion-experiment-test-new-admin-upgrade-design-copy-for.yml new file mode 100644 index 00000000000..12de1e6aadd --- /dev/null +++ b/changelogs/unreleased/32419-growth-conversion-experiment-test-new-admin-upgrade-design-copy-for.yml @@ -0,0 +1,5 @@ +--- +title: Upgrade design/copy for issue weights locked feature +merge_request: 17352 +author: +type: changed diff --git a/changelogs/unreleased/lm-grafana-auth-checkbox.yml b/changelogs/unreleased/lm-grafana-auth-checkbox.yml new file mode 100644 index 00000000000..39642f656ec --- /dev/null +++ b/changelogs/unreleased/lm-grafana-auth-checkbox.yml @@ -0,0 +1,5 @@ +--- +title: Add grafana integration active status checkbox +merge_request: 19255 +author: +type: added diff --git a/doc/development/fe_guide/development_process.md b/doc/development/fe_guide/development_process.md index 3724bf60757..5b02098f020 100644 --- a/doc/development/fe_guide/development_process.md +++ b/doc/development/fe_guide/development_process.md @@ -73,7 +73,7 @@ With the purpose of being [respectful of others' time](https://about.gitlab.com/ - Before assigning to a maintainer, assign to a reviewer. - If you assigned a merge request, or pinged someone directly, keep in mind that we work in different timezones and asynchronously, so be patient. Unless the merge request is urgent (like fixing a broken master), please don't DM or reassign the merge request before waiting for a 24-hour window. - If you have a question regarding your merge request/issue, make it on the merge request/issue. When we DM each other, we no longer have a SSOT and [no one else is able to contribute](https://about.gitlab.com/handbook/values/#public-by-default). -- When you have a big WIP merge request with many changes, you're adivsed to get the review started before adding/removing significant code. Make sure it is assigned well before the release cut-off, as the reviewer(s)/maintainer(s) would always prioritize reviewing finished MRs before WIP ones. +- When you have a big WIP merge request with many changes, you're advised to get the review started before adding/removing significant code. Make sure it is assigned well before the release cut-off, as the reviewer(s)/maintainer(s) would always prioritize reviewing finished MRs before WIP ones. - Make sure to remove the WIP title before the last round of review. ### Share your work early diff --git a/doc/user/group/saml_sso/index.md b/doc/user/group/saml_sso/index.md index ee55d7e2a11..1bf03acc7ba 100644 --- a/doc/user/group/saml_sso/index.md +++ b/doc/user/group/saml_sso/index.md @@ -26,6 +26,23 @@ SAML SSO for GitLab.com groups does not sync users between providers without usi ![Issuer and callback for configuring SAML identity provider with GitLab.com](img/group_saml_configuration_information.png) +### NameID + +GitLab.com uses the SAML NameID to identify users. The NameID element: + +- Is a required field in the SAML response. +- Must be unique to each user. +- Must be a persistent value that will never change, such as a randomly generated unique user ID. +- Is case sensitive. The NameID must match exactly on subsequent login attempts, so should not rely on user input that could change between upper and lower case. +- Should not be an email address or username. We strongly recommend against these as it is hard to guarantee they will never change, for example when a person's name changes. Email addresses are also case-insensitive, which can result in users being unable to sign in. + +CAUTION: **Warning:** +Once users have signed into GitLab using the SSO SAML setup, changing the `NameID` will break the configuration and potentially lock users out of the GitLab group. + +#### NameID Format + +We recommend setting the NameID format to `Persistent` unless using a field (such as email) that requires a different format. + ### SSO enforcement SSO enforcement was: @@ -58,25 +75,16 @@ Since use of the group managed account requires the use of SSO, users of group m - The user will be unable to access the group (their credentials will no longer work on the identity provider when prompted to SSO). - Contributions in the group (e.g. issues, merge requests) will remain intact. -### NameID - -GitLab.com uses the SAML NameID to identify users. The NameID element: - -- Is a required field in the SAML response. -- Must be unique to each user. -- Must be a persistent value that will never change, such as a randomly generated unique user ID. -- Is case sensitive. The NameID must match exactly on subsequent login attempts, so should not rely on user input that could change between upper and lower case. - -We strongly recommend against using Email as the NameID as it is hard to guarantee it will never change, for example when a person's name changes. Similarly usernames should be avoided if possible. +#### Assertions -### Assertions +When using Group Manged Accounts, the following user details need to be passed to GitLab as SAML Assertions in order for us to be able to create a user: -| Field | Supported keys | -|-------|----------------| +| Field | Supported keys | +|-----------------|----------------| | Email (required)| `email`, `mail` | -| Full Name | `name` | -| First Name | `first_name`, `firstname`, `firstName` | -| Last Name | `last_name`, `lastname`, `lastName` | +| Full Name | `name` | +| First Name | `first_name`, `firstname`, `firstName` | +| Last Name | `last_name`, `lastname`, `lastName` | ## Metadata configuration diff --git a/doc/user/group/saml_sso/scim_setup.md b/doc/user/group/saml_sso/scim_setup.md index 7e2b9f7513b..392b27bb42f 100644 --- a/doc/user/group/saml_sso/scim_setup.md +++ b/doc/user/group/saml_sso/scim_setup.md @@ -66,8 +66,13 @@ You can then test the connection by clicking on **Test Connection**. If the conn 1. Click **Delete** next to the `mail` mapping. 1. Map `userPrincipalName` to `emails[type eq "work"].value` and change it's **Matching precedence** to `2`. 1. Map `mailNickname` to `userName`. -1. Create a new mapping by clicking **Add New Mapping** then set **Source attribute** to `objectId`, **Target attribute** to `id`, **Match objects using this attribute** to `Yes`, and **Matching precedence** to `1`. -1. Create a new mapping by clicking **Add New Mapping** then set **Source attribute** to `objectId`, and **Target attribute** to `externalId`. +1. Determine how GitLab will uniquely identify users. + + - Use `objectId` unless users already have SAML linked for your group. + - If you already have users with SAML linked then use the `Name ID` value from the [SAML configuration](#azure). Using a different value will likely cause duplicate users and prevent users from accessing the GitLab group. + +1. Create a new mapping by clicking **Add New Mapping** then set **Source attribute** to the unique identifier determined above, **Target attribute** to `id`, **Match objects using this attribute** to `Yes`, and **Matching precedence** to `1`. +1. Create a new mapping by clicking **Add New Mapping** then set **Source attribute** to the unique identifier determined above, and **Target attribute** to `externalId`. 1. Click the `userPrincipalName` mapping and change **Match objects using this attribute** to `No`. Save your changes and you should have the following configuration: @@ -99,6 +104,9 @@ You can then test the connection by clicking on **Test Connection**. If the conn Once enabled, the synchronization details and any errors will appear on the bottom of the **Provisioning** screen, together with a link to the audit logs. +CAUTION: **Warning:** +Once synchronized, changing the field mapped to `id` and `externalId` will likely cause provisioning errors, duplicate users, and prevent existing users from accessing the GitLab group. + ## Troubleshooting ### Testing Azure connection: invalid credentials diff --git a/doc/user/project/issues/design_management.md b/doc/user/project/issues/design_management.md index 24044310451..c9f06c6339e 100644 --- a/doc/user/project/issues/design_management.md +++ b/doc/user/project/issues/design_management.md @@ -33,6 +33,10 @@ to be enabled: project level, navigate to your project's **Settings > General**, expand **Visibility, project features, permissions** and enable **Git Large File Storage**. +Design Management requires that projects are using +[hashed storage](../../../administration/repository_storage_types.html#hashed-storage) +(the default storage type since v10.0). + ## Limitations - Files uploaded must have a file extension of either `png`, `jpg`, `jpeg`, `gif`, `bmp`, `tiff` or `ico`. diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 2a18ebf8d97..405f6be75b3 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -2917,9 +2917,6 @@ msgstr "" msgid "Certificate (PEM)" msgstr "" -msgid "Change Weight" -msgstr "" - msgid "Change assignee" msgstr "" @@ -8307,6 +8304,9 @@ msgstr "" msgid "GrafanaIntegration|API Token" msgstr "" +msgid "GrafanaIntegration|Active" +msgstr "" + msgid "GrafanaIntegration|Embed Grafana charts in GitLab issues." msgstr "" @@ -13483,12 +13483,24 @@ msgstr "" msgid "Promotions|Epics let you manage your portfolio of projects more efficiently and with less effort by tracking groups of issues that share a theme, across projects and milestones." msgstr "" +msgid "Promotions|Learn more" +msgstr "" + +msgid "Promotions|See the other features in the %{subscription_link_start}bronze plan%{subscriptions_link_end}" +msgstr "" + msgid "Promotions|This feature is locked." msgstr "" msgid "Promotions|Upgrade plan" msgstr "" +msgid "Promotions|Weighting your issue" +msgstr "" + +msgid "Promotions|When you have a lot of issues, it can be hard to get an overview. By adding a weight to your issues, you can get a better idea of the effort, cost, required time, or value of each, and so better manage them." +msgstr "" + msgid "Prompt users to upload SSH keys" msgstr "" @@ -18227,9 +18239,6 @@ msgstr "" msgid "Upgrade your plan to activate Group Webhooks." msgstr "" -msgid "Upgrade your plan to activate Issue weight." -msgstr "" - msgid "Upgrade your plan to improve Issue boards." msgstr "" diff --git a/qa/qa/page/dashboard/projects.rb b/qa/qa/page/dashboard/projects.rb index 378ac793f7b..c103bc26a36 100644 --- a/qa/qa/page/dashboard/projects.rb +++ b/qa/qa/page/dashboard/projects.rb @@ -18,6 +18,10 @@ module QA '/' end + def clear_project_filter + fill_element(:project_filter_form, "") + end + private def filter_by_name(name) diff --git a/qa/qa/page/project/settings/ci_cd.rb b/qa/qa/page/project/settings/ci_cd.rb index 45040cf4660..46f93fad61e 100644 --- a/qa/qa/page/project/settings/ci_cd.rb +++ b/qa/qa/page/project/settings/ci_cd.rb @@ -35,3 +35,5 @@ module QA end end end + +QA::Page::Project::Settings::CICD.prepend_if_ee('QA::EE::Page::Project::Settings::CICD') diff --git a/spec/frontend/grafana_integration/components/__snapshots__/grafana_integration_spec.js.snap b/spec/frontend/grafana_integration/components/__snapshots__/grafana_integration_spec.js.snap index 43239da344f..99f669dba5a 100644 --- a/spec/frontend/grafana_integration/components/__snapshots__/grafana_integration_spec.js.snap +++ b/spec/frontend/grafana_integration/components/__snapshots__/grafana_integration_spec.js.snap @@ -35,6 +35,15 @@ exports[`grafana integration component default state to match the default snapsh class="settings-content" > <form> + <glformcheckbox-stub + class="mb-4" + id="grafana-integration-enabled" + > + + Active + + </glformcheckbox-stub> + <glformgroup-stub description="Enter the base URL of the Grafana instance." label="Grafana URL" diff --git a/spec/frontend/grafana_integration/components/grafana_integration_spec.js b/spec/frontend/grafana_integration/components/grafana_integration_spec.js index 594ea94dc6a..c098ada0519 100644 --- a/spec/frontend/grafana_integration/components/grafana_integration_spec.js +++ b/spec/frontend/grafana_integration/components/grafana_integration_spec.js @@ -86,6 +86,7 @@ describe('grafana integration component', () => { grafana_integration_attributes: { grafana_url: grafanaIntegrationUrl, token: grafanaIntegrationToken, + enabled: false, }, }, }, diff --git a/spec/frontend/grafana_integration/store/mutations_spec.js b/spec/frontend/grafana_integration/store/mutations_spec.js index d9b8c258623..18e87394189 100644 --- a/spec/frontend/grafana_integration/store/mutations_spec.js +++ b/spec/frontend/grafana_integration/store/mutations_spec.js @@ -25,4 +25,11 @@ describe('grafana integration mutations', () => { expect(localState.grafanaToken).toBe(mockToken); }); }); + describe('SET_GRAFANA_ENABLED', () => { + it('updates grafanaEnabled for integration', () => { + mutations.SET_GRAFANA_ENABLED(localState, true); + + expect(localState.grafanaEnabled).toBe(true); + }); + }); }); diff --git a/spec/policies/personal_snippet_policy_spec.rb b/spec/policies/personal_snippet_policy_spec.rb index 9a74a3d07f3..36b4ac16cf0 100644 --- a/spec/policies/personal_snippet_policy_spec.rb +++ b/spec/policies/personal_snippet_policy_spec.rb @@ -20,6 +20,19 @@ describe PersonalSnippetPolicy do described_class.new(user, snippet) end + shared_examples 'admin access' do + context 'admin user' do + subject { permissions(admin_user) } + + it do + is_expected.to be_allowed(:read_personal_snippet) + is_expected.to be_allowed(:create_note) + is_expected.to be_allowed(:award_emoji) + is_expected.to be_allowed(*author_permissions) + end + end + end + context 'public snippet' do let(:snippet) { create(:personal_snippet, :public) } @@ -55,6 +68,8 @@ describe PersonalSnippetPolicy do is_expected.to be_allowed(*author_permissions) end end + + it_behaves_like 'admin access' end context 'internal snippet' do @@ -103,6 +118,8 @@ describe PersonalSnippetPolicy do is_expected.to be_allowed(*author_permissions) end end + + it_behaves_like 'admin access' end context 'private snippet' do @@ -130,17 +147,6 @@ describe PersonalSnippetPolicy do end end - context 'admin user' do - subject { permissions(admin_user) } - - it do - is_expected.to be_allowed(:read_personal_snippet) - is_expected.to be_disallowed(:create_note) - is_expected.to be_disallowed(:award_emoji) - is_expected.to be_disallowed(*author_permissions) - end - end - context 'external user' do subject { permissions(external_user) } @@ -162,5 +168,7 @@ describe PersonalSnippetPolicy do is_expected.to be_allowed(*author_permissions) end end + + it_behaves_like 'admin access' end end |