diff options
177 files changed, 2378 insertions, 1516 deletions
diff --git a/.gitlab/merge_request_templates/Database Changes.md b/.gitlab/merge_request_templates/Database Changes.md index 2a5c8267872..8302b3b30c7 100644 --- a/.gitlab/merge_request_templates/Database Changes.md +++ b/.gitlab/merge_request_templates/Database Changes.md @@ -1,20 +1,5 @@ -Remove this section and replace it with a description of your MR. Also follow the -checklist below and check off any tasks that are done. If a certain task can not -be done you should explain so in the MR body. You are free to remove any -sections that do not apply to your MR. - -When gathering statistics (e.g. the output of `EXPLAIN ANALYZE`) you should make -sure your database has enough data. Having around 10 000 rows in the tables -being queries should provide a reasonable estimate of how a query will behave. -Also make sure that PostgreSQL uses the following settings: - -* `random_page_cost`: `1` -* `work_mem`: `16MB` -* `maintenance_work_mem`: at least `64MB` -* `shared_buffers`: at least `256MB` - -If you have access to GitLab.com's staging environment you should also run your -measurements there, and include the results in this MR. +Add a description of your merge request here. Merge requests without an adequate +description will not be reviewed until one is added. ## Database Checklist @@ -23,34 +8,23 @@ When adding migrations: - [ ] Updated `db/schema.rb` - [ ] Added a `down` method so the migration can be reverted - [ ] Added the output of the migration(s) to the MR body -- [ ] Added the execution time of the migration(s) to the MR body -- [ ] Added tests for the migration in `spec/migrations` if necessary (e.g. when - migrating data) -- [ ] Made sure the migration won't interfere with a running GitLab cluster, - for example by disabling transactions for long running migrations +- [ ] Added tests for the migration in `spec/migrations` if necessary (e.g. when migrating data) When adding or modifying queries to improve performance: -- [ ] Included the raw SQL queries of the relevant queries -- [ ] Included the output of `EXPLAIN ANALYZE` and execution timings of the - relevant queries -- [ ] Added tests for the relevant changes - -When adding indexes: - -- [ ] Described the need for these indexes in the MR body -- [ ] Made sure existing indexes can not be reused instead +- [ ] Included data that shows the performance improvement, preferably in the form of a benchmark +- [ ] Included the output of `EXPLAIN (ANALYZE, BUFFERS)` of the relevant queries When adding foreign keys to existing tables: -- [ ] Included a migration to remove orphaned rows in the source table +- [ ] Included a migration to remove orphaned rows in the source table before adding the foreign key - [ ] Removed any instances of `dependent: ...` that may no longer be necessary When adding tables: -- [ ] Ordered columns based on their type sizes in descending order -- [ ] Added foreign keys if necessary -- [ ] Added indexes if necessary +- [ ] Ordered columns based on the [Ordering Table Columns](https://docs.gitlab.com/ee/development/ordering_table_columns.html#ordering-table-columns) guidelines +- [ ] Added foreign keys to any columns pointing to data in other tables +- [ ] Added indexes for fields that are used in statements such as WHERE, ORDER BY, GROUP BY, and JOINs When removing columns, tables, indexes or other structures: @@ -64,8 +38,6 @@ When removing columns, tables, indexes or other structures: - [ ] API support added - [ ] Tests added for this feature/bug - Review - - [ ] Has been reviewed by UX - - [ ] Has been reviewed by Frontend - [ ] Has been reviewed by Backend - [ ] Has been reviewed by Database - [ ] Conform by the [merge request performance guides](http://docs.gitlab.com/ce/development/merge_request_performance_guidelines.html) diff --git a/CHANGELOG.md b/CHANGELOG.md index 48282f67ed4..221626e7bf8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,13 @@ documentation](doc/development/changelog.md) for instructions on adding your own entry. +## 10.2.1 (2017-11-22) + +### Fixed (1 change) + +- Force disable Prometheus metrics. + + ## 10.2.0 (2017-11-22) ### Security (4 changes) diff --git a/app/assets/javascripts/environments/components/container.vue b/app/assets/javascripts/environments/components/container.vue new file mode 100644 index 00000000000..3236077c3cf --- /dev/null +++ b/app/assets/javascripts/environments/components/container.vue @@ -0,0 +1,71 @@ +<script> + import loadingIcon from '../../vue_shared/components/loading_icon.vue'; + import tablePagination from '../../vue_shared/components/table_pagination.vue'; + import environmentTable from '../components/environments_table.vue'; + + export default { + props: { + isLoading: { + type: Boolean, + required: true, + }, + environments: { + type: Array, + required: true, + }, + pagination: { + type: Object, + required: true, + }, + canCreateDeployment: { + type: Boolean, + required: true, + }, + canReadEnvironment: { + type: Boolean, + required: true, + }, + }, + components: { + environmentTable, + loadingIcon, + tablePagination, + }, + + methods: { + onChangePage(page) { + this.$emit('onChangePage', page); + }, + }, + }; +</script> + +<template> + <div class="environments-container"> + + <loading-icon + label="Loading environments" + v-if="isLoading" + size="3" + /> + + <slot name="emptyState"></slot> + + <div + class="table-holder" + v-if="!isLoading && environments.length > 0"> + + <environment-table + :environments="environments" + :can-create-deployment="canCreateDeployment" + :can-read-environment="canReadEnvironment" + /> + + <table-pagination + v-if="pagination && pagination.totalPages > 1" + :change="onChangePage" + :pageInfo="pagination" + /> + </div> + </div> +</template> diff --git a/app/assets/javascripts/environments/components/empty_state.vue b/app/assets/javascripts/environments/components/empty_state.vue new file mode 100644 index 00000000000..2646f08c8e6 --- /dev/null +++ b/app/assets/javascripts/environments/components/empty_state.vue @@ -0,0 +1,42 @@ +<script> + export default { + name: 'environmentsEmptyState', + props: { + newPath: { + type: String, + required: true, + }, + canCreateEnvironment: { + type: Boolean, + required: true, + }, + helpPath: { + type: String, + required: true, + }, + }, + }; +</script> +<template> + <div class="blank-state-row"> + <div class="blank-state-center"> + <h2 class="blank-state-title js-blank-state-title"> + {{s__("Environments|You don't have any environments right now.")}} + </h2> + <p class="blank-state-text"> + {{s__("Environments|Environments are places where code gets deployed, such as staging or production.")}} + <br /> + <a :href="helpPath"> + {{s__("Environments|Read more about environments")}} + </a> + </p> + + <a + v-if="canCreateEnvironment" + :href="newPath" + class="btn btn-create js-new-environment-button"> + {{s__("Environments|New environment")}} + </a> + </div> + </div> +</template> diff --git a/app/assets/javascripts/environments/components/environment.vue b/app/assets/javascripts/environments/components/environment.vue deleted file mode 100644 index ffb7757bed8..00000000000 --- a/app/assets/javascripts/environments/components/environment.vue +++ /dev/null @@ -1,270 +0,0 @@ -<script> -import Visibility from 'visibilityjs'; -import Flash from '../../flash'; -import EnvironmentsService from '../services/environments_service'; -import environmentTable from './environments_table.vue'; -import EnvironmentsStore from '../stores/environments_store'; -import loadingIcon from '../../vue_shared/components/loading_icon.vue'; -import tablePagination from '../../vue_shared/components/table_pagination.vue'; -import { convertPermissionToBoolean, getParameterByName, setParamInURL } from '../../lib/utils/common_utils'; -import eventHub from '../event_hub'; -import Poll from '../../lib/utils/poll'; -import environmentsMixin from '../mixins/environments_mixin'; - -export default { - - components: { - environmentTable, - tablePagination, - loadingIcon, - }, - - mixins: [ - environmentsMixin, - ], - - data() { - const environmentsData = document.querySelector('#environments-list-view').dataset; - const store = new EnvironmentsStore(); - - return { - store, - state: store.state, - visibility: 'available', - isLoading: false, - cssContainerClass: environmentsData.cssClass, - endpoint: environmentsData.environmentsDataEndpoint, - canCreateDeployment: environmentsData.canCreateDeployment, - canReadEnvironment: environmentsData.canReadEnvironment, - canCreateEnvironment: environmentsData.canCreateEnvironment, - projectEnvironmentsPath: environmentsData.projectEnvironmentsPath, - projectStoppedEnvironmentsPath: environmentsData.projectStoppedEnvironmentsPath, - newEnvironmentPath: environmentsData.newEnvironmentPath, - helpPagePath: environmentsData.helpPagePath, - isMakingRequest: false, - - // Pagination Properties, - paginationInformation: {}, - pageNumber: 1, - }; - }, - - computed: { - scope() { - return getParameterByName('scope'); - }, - - canReadEnvironmentParsed() { - return convertPermissionToBoolean(this.canReadEnvironment); - }, - - canCreateDeploymentParsed() { - return convertPermissionToBoolean(this.canCreateDeployment); - }, - - canCreateEnvironmentParsed() { - return convertPermissionToBoolean(this.canCreateEnvironment); - }, - }, - - /** - * Fetches all the environments and stores them. - * Toggles loading property. - */ - created() { - const scope = getParameterByName('scope') || this.visibility; - const page = getParameterByName('page') || this.pageNumber; - - this.service = new EnvironmentsService(this.endpoint); - - const poll = new Poll({ - resource: this.service, - method: 'get', - data: { scope, page }, - successCallback: this.successCallback, - errorCallback: this.errorCallback, - notificationCallback: (isMakingRequest) => { - this.isMakingRequest = isMakingRequest; - }, - }); - - if (!Visibility.hidden()) { - this.isLoading = true; - poll.makeRequest(); - } - - Visibility.change(() => { - if (!Visibility.hidden()) { - poll.restart(); - } else { - poll.stop(); - } - }); - - eventHub.$on('toggleFolder', this.toggleFolder); - eventHub.$on('postAction', this.postAction); - }, - - beforeDestroy() { - eventHub.$off('toggleFolder'); - eventHub.$off('postAction'); - }, - - methods: { - toggleFolder(folder) { - this.store.toggleFolder(folder); - - if (!folder.isOpen) { - this.fetchChildEnvironments(folder, true); - } - }, - - /** - * Will change the page number and update the URL. - * - * @param {Number} pageNumber desired page to go to. - * @return {String} - */ - changePage(pageNumber) { - const param = setParamInURL('page', pageNumber); - - gl.utils.visitUrl(param); - return param; - }, - - fetchEnvironments() { - const scope = getParameterByName('scope') || this.visibility; - const page = getParameterByName('page') || this.pageNumber; - - this.isLoading = true; - - return this.service.get({ scope, page }) - .then(this.successCallback) - .catch(this.errorCallback); - }, - - fetchChildEnvironments(folder, showLoader = false) { - this.store.updateEnvironmentProp(folder, 'isLoadingFolderContent', showLoader); - - this.service.getFolderContent(folder.folder_path) - .then(resp => resp.json()) - .then(response => this.store.setfolderContent(folder, response.environments)) - .then(() => this.store.updateEnvironmentProp(folder, 'isLoadingFolderContent', false)) - .catch(() => { - // eslint-disable-next-line no-new - new Flash('An error occurred while fetching the environments.'); - this.store.updateEnvironmentProp(folder, 'isLoadingFolderContent', false); - }); - }, - - postAction(endpoint) { - if (!this.isMakingRequest) { - this.isLoading = true; - - this.service.postAction(endpoint) - .then(() => this.fetchEnvironments()) - .catch(() => new Flash('An error occurred while making the request.')); - } - }, - - successCallback(resp) { - this.saveData(resp); - - // We need to verify if any folder is open to also update it - const openFolders = this.store.getOpenFolders(); - if (openFolders.length) { - openFolders.forEach(folder => this.fetchChildEnvironments(folder)); - } - }, - - errorCallback() { - this.isLoading = false; - // eslint-disable-next-line no-new - new Flash('An error occurred while fetching the environments.'); - }, - }, -}; -</script> -<template> - <div :class="cssContainerClass"> - <div class="top-area"> - <ul - v-if="!isLoading" - class="nav-links"> - <li :class="{ active: scope === null || scope === 'available' }"> - <a :href="projectEnvironmentsPath"> - Available - <span class="badge js-available-environments-count"> - {{state.availableCounter}} - </span> - </a> - </li> - <li :class="{ active : scope === 'stopped' }"> - <a :href="projectStoppedEnvironmentsPath"> - Stopped - <span class="badge js-stopped-environments-count"> - {{state.stoppedCounter}} - </span> - </a> - </li> - </ul> - <div - v-if="canCreateEnvironmentParsed && !isLoading" - class="nav-controls"> - <a - :href="newEnvironmentPath" - class="btn btn-create"> - New environment - </a> - </div> - </div> - - <div class="environments-container"> - <loading-icon - label="Loading environments" - size="3" - v-if="isLoading" - /> - - <div - class="blank-state-row" - v-if="!isLoading && state.environments.length === 0"> - <div class="blank-state-center"> - <h2 class="blank-state-title js-blank-state-title"> - You don't have any environments right now. - </h2> - <p class="blank-state-text"> - Environments are places where code gets deployed, such as staging or production. - <br /> - <a :href="helpPagePath"> - Read more about environments - </a> - </p> - - <a - v-if="canCreateEnvironmentParsed" - :href="newEnvironmentPath" - class="btn btn-create js-new-environment-button"> - New environment - </a> - </div> - </div> - - <div - class="table-holder" - v-if="!isLoading && state.environments.length > 0"> - - <environment-table - :environments="state.environments" - :can-create-deployment="canCreateDeploymentParsed" - :can-read-environment="canReadEnvironmentParsed" - /> - </div> - - <table-pagination - v-if="state.paginationInformation && state.paginationInformation.totalPages > 1" - :change="changePage" - :pageInfo="state.paginationInformation" /> - </div> - </div> -</template> diff --git a/app/assets/javascripts/environments/components/environment_external_url.vue b/app/assets/javascripts/environments/components/environment_external_url.vue index 6b749814ea4..520c3ac8ace 100644 --- a/app/assets/javascripts/environments/components/environment_external_url.vue +++ b/app/assets/javascripts/environments/components/environment_external_url.vue @@ -1,5 +1,6 @@ <script> import tooltip from '../../vue_shared/directives/tooltip'; +import { s__ } from '../../locale'; /** * Renders the external url link in environments table. @@ -18,7 +19,7 @@ export default { computed: { title() { - return 'Open'; + return s__('Environments|Open'); }, }, }; diff --git a/app/assets/javascripts/environments/components/environment_item.vue b/app/assets/javascripts/environments/components/environment_item.vue index 9d25f806c0d..2f0e397aa45 100644 --- a/app/assets/javascripts/environments/components/environment_item.vue +++ b/app/assets/javascripts/environments/components/environment_item.vue @@ -432,7 +432,7 @@ export default { v-if="!model.isFolder" class="table-mobile-header" role="rowheader"> - Environment + {{s__("Environments|Environment")}} </div> <a v-if="!model.isFolder" @@ -505,7 +505,7 @@ export default { <div role="rowheader" class="table-mobile-header"> - Commit + {{s__("Environments|Commit")}} </div> <div v-if="hasLastDeploymentKey" @@ -521,7 +521,7 @@ export default { <div v-if="!hasLastDeploymentKey" class="commit-title table-mobile-content"> - No deployments yet + {{s__("Environments|No deployments yet")}} </div> </div> @@ -531,7 +531,7 @@ export default { <div role="rowheader" class="table-mobile-header"> - Updated + {{s__("Environments|Updated")}} </div> <span v-if="canShowDate" diff --git a/app/assets/javascripts/environments/components/environment_monitoring.vue b/app/assets/javascripts/environments/components/environment_monitoring.vue index 1655561cdd3..b45af1a5ebc 100644 --- a/app/assets/javascripts/environments/components/environment_monitoring.vue +++ b/app/assets/javascripts/environments/components/environment_monitoring.vue @@ -34,6 +34,7 @@ export default { :aria-label="title"> <i class="fa fa-area-chart" - aria-hidden="true" /> + aria-hidden="true" + /> </a> </template> diff --git a/app/assets/javascripts/environments/components/environment_rollback.vue b/app/assets/javascripts/environments/components/environment_rollback.vue index 49dba38edfb..92a596bfd33 100644 --- a/app/assets/javascripts/environments/components/environment_rollback.vue +++ b/app/assets/javascripts/environments/components/environment_rollback.vue @@ -48,10 +48,10 @@ export default { :disabled="isLoading"> <span v-if="isLastDeployment"> - Re-deploy + {{s__("Environments|Re-deploy")}} </span> <span v-else> - Rollback + {{s__("Environments|Rollback")}} </span> <loading-icon v-if="isLoading" /> diff --git a/app/assets/javascripts/environments/components/environments_app.vue b/app/assets/javascripts/environments/components/environments_app.vue new file mode 100644 index 00000000000..2592909734f --- /dev/null +++ b/app/assets/javascripts/environments/components/environments_app.vue @@ -0,0 +1,128 @@ +<script> + import Flash from '../../flash'; + import { s__ } from '../../locale'; + import emptyState from './empty_state.vue'; + import eventHub from '../event_hub'; + import environmentsMixin from '../mixins/environments_mixin'; + import CIPaginationMixin from '../../vue_shared/mixins/ci_pagination_api_mixin'; + + export default { + props: { + endpoint: { + type: String, + required: true, + }, + canCreateEnvironment: { + type: Boolean, + required: true, + }, + canCreateDeployment: { + type: Boolean, + required: true, + }, + canReadEnvironment: { + type: Boolean, + required: true, + }, + cssContainerClass: { + type: String, + required: true, + }, + newEnvironmentPath: { + type: String, + required: true, + }, + helpPagePath: { + type: String, + required: true, + }, + }, + components: { + emptyState, + }, + + mixins: [ + CIPaginationMixin, + environmentsMixin, + ], + + created() { + eventHub.$on('toggleFolder', this.toggleFolder); + }, + + beforeDestroy() { + eventHub.$off('toggleFolder'); + }, + + methods: { + toggleFolder(folder) { + this.store.toggleFolder(folder); + + if (!folder.isOpen) { + this.fetchChildEnvironments(folder, true); + } + }, + + fetchChildEnvironments(folder, showLoader = false) { + this.store.updateEnvironmentProp(folder, 'isLoadingFolderContent', showLoader); + + this.service.getFolderContent(folder.folder_path) + .then(resp => resp.json()) + .then(response => this.store.setfolderContent(folder, response.environments)) + .then(() => this.store.updateEnvironmentProp(folder, 'isLoadingFolderContent', false)) + .catch(() => { + Flash(s__('Environments|An error occurred while fetching the environments.')); + this.store.updateEnvironmentProp(folder, 'isLoadingFolderContent', false); + }); + }, + + successCallback(resp) { + this.saveData(resp); + + // We need to verify if any folder is open to also update it + const openFolders = this.store.getOpenFolders(); + if (openFolders.length) { + openFolders.forEach(folder => this.fetchChildEnvironments(folder)); + } + }, + }, + }; +</script> +<template> + <div :class="cssContainerClass"> + <div class="top-area"> + <tabs + :tabs="tabs" + @onChangeTab="onChangeTab" + scope="environments" + /> + + <div + v-if="canCreateEnvironment && !isLoading" + class="nav-controls"> + <a + :href="newEnvironmentPath" + class="btn btn-create"> + {{s__("Environments|New environment")}} + </a> + </div> + </div> + + <container + :is-loading="isLoading" + :environments="state.environments" + :pagination="state.paginationInformation" + :can-create-deployment="canCreateDeployment" + :can-read-environment="canReadEnvironment" + @onChangePage="onChangePage" + > + <empty-state + slot="emptyState" + v-if="!isLoading && state.environments.length === 0" + :new-path="newEnvironmentPath" + :help-path="helpPagePath" + :can-create-environment="canCreateEnvironment" + /> + </container> + </div> +</template> diff --git a/app/assets/javascripts/environments/components/environments_table.vue b/app/assets/javascripts/environments/components/environments_table.vue index 175cc8f1f72..c04da4b81b7 100644 --- a/app/assets/javascripts/environments/components/environments_table.vue +++ b/app/assets/javascripts/environments/components/environments_table.vue @@ -2,12 +2,12 @@ /** * Render environments table. */ -import EnvironmentTableRowComponent from './environment_item.vue'; +import environmentItem from './environment_item.vue'; import loadingIcon from '../../vue_shared/components/loading_icon.vue'; export default { components: { - 'environment-item': EnvironmentTableRowComponent, + environmentItem, loadingIcon, }, @@ -42,19 +42,19 @@ export default { <div class="ci-table" role="grid"> <div class="gl-responsive-table-row table-row-header" role="row"> <div class="table-section section-10 environments-name" role="columnheader"> - Environment + {{s__("Environments|Environment")}} </div> <div class="table-section section-10 environments-deploy" role="columnheader"> - Deployment + {{s__("Environments|Deployment")}} </div> <div class="table-section section-15 environments-build" role="columnheader"> - Job + {{s__("Environments|Job")}} </div> <div class="table-section section-25 environments-commit" role="columnheader"> - Commit + {{s__("Environments|Commit")}} </div> <div class="table-section section-10 environments-date" role="columnheader"> - Updated + {{s__("Environments|Updated")}} </div> </div> <template @@ -86,7 +86,7 @@ export default { <a :href="folderUrl(model)" class="btn btn-default"> - Show all + {{s__("Environments|Show all")}} </a> </div> </div> diff --git a/app/assets/javascripts/environments/environments_bundle.js b/app/assets/javascripts/environments/environments_bundle.js index c0662125f28..2e0a4001b7c 100644 --- a/app/assets/javascripts/environments/environments_bundle.js +++ b/app/assets/javascripts/environments/environments_bundle.js @@ -1,10 +1,39 @@ import Vue from 'vue'; -import EnvironmentsComponent from './components/environment.vue'; +import environmentsComponent from './components/environments_app.vue'; +import { convertPermissionToBoolean } from '../lib/utils/common_utils'; +import Translate from '../vue_shared/translate'; + +Vue.use(Translate); document.addEventListener('DOMContentLoaded', () => new Vue({ el: '#environments-list-view', components: { - 'environments-table-app': EnvironmentsComponent, + environmentsComponent, + }, + data() { + const environmentsData = document.querySelector(this.$options.el).dataset; + + return { + endpoint: environmentsData.environmentsDataEndpoint, + newEnvironmentPath: environmentsData.newEnvironmentPath, + helpPagePath: environmentsData.helpPagePath, + cssContainerClass: environmentsData.cssClass, + canCreateEnvironment: convertPermissionToBoolean(environmentsData.canCreateEnvironment), + canCreateDeployment: convertPermissionToBoolean(environmentsData.canCreateDeployment), + canReadEnvironment: convertPermissionToBoolean(environmentsData.canReadEnvironment), + }; + }, + render(createElement) { + return createElement('environments-component', { + props: { + endpoint: this.endpoint, + newEnvironmentPath: this.newEnvironmentPath, + helpPagePath: this.helpPagePath, + cssContainerClass: this.cssContainerClass, + canCreateEnvironment: this.canCreateEnvironment, + canCreateDeployment: this.canCreateDeployment, + canReadEnvironment: this.canReadEnvironment, + }, + }); }, - render: createElement => createElement('environments-table-app'), })); diff --git a/app/assets/javascripts/environments/folder/environments_folder_bundle.js b/app/assets/javascripts/environments/folder/environments_folder_bundle.js index 9add8c3d721..5d2d14c7682 100644 --- a/app/assets/javascripts/environments/folder/environments_folder_bundle.js +++ b/app/assets/javascripts/environments/folder/environments_folder_bundle.js @@ -1,10 +1,35 @@ import Vue from 'vue'; -import EnvironmentsFolderComponent from './environments_folder_view.vue'; +import environmentsFolderApp from './environments_folder_view.vue'; +import { convertPermissionToBoolean } from '../../lib/utils/common_utils'; +import Translate from '../../vue_shared/translate'; + +Vue.use(Translate); document.addEventListener('DOMContentLoaded', () => new Vue({ el: '#environments-folder-list-view', components: { - 'environments-folder-app': EnvironmentsFolderComponent, + environmentsFolderApp, + }, + data() { + const environmentsData = document.querySelector(this.$options.el).dataset; + + return { + endpoint: environmentsData.endpoint, + folderName: environmentsData.folderName, + cssContainerClass: environmentsData.cssClass, + canCreateDeployment: convertPermissionToBoolean(environmentsData.canCreateDeployment), + canReadEnvironment: convertPermissionToBoolean(environmentsData.canReadEnvironment), + }; + }, + render(createElement) { + return createElement('environments-folder-app', { + props: { + endpoint: this.endpoint, + folderName: this.folderName, + cssContainerClass: this.cssContainerClass, + canCreateDeployment: this.canCreateDeployment, + canReadEnvironment: this.canReadEnvironment, + }, + }); }, - render: createElement => createElement('environments-folder-app'), })); diff --git a/app/assets/javascripts/environments/folder/environments_folder_view.vue b/app/assets/javascripts/environments/folder/environments_folder_view.vue index b155560df9d..27418bad01a 100644 --- a/app/assets/javascripts/environments/folder/environments_folder_view.vue +++ b/app/assets/javascripts/environments/folder/environments_folder_view.vue @@ -1,168 +1,40 @@ <script> -import Visibility from 'visibilityjs'; -import Flash from '../../flash'; -import EnvironmentsService from '../services/environments_service'; -import environmentTable from '../components/environments_table.vue'; -import EnvironmentsStore from '../stores/environments_store'; -import loadingIcon from '../../vue_shared/components/loading_icon.vue'; -import tablePagination from '../../vue_shared/components/table_pagination.vue'; -import Poll from '../../lib/utils/poll'; -import eventHub from '../event_hub'; -import environmentsMixin from '../mixins/environments_mixin'; -import { convertPermissionToBoolean, getParameterByName, setParamInURL } from '../../lib/utils/common_utils'; - -export default { - components: { - environmentTable, - tablePagination, - loadingIcon, - }, - - mixins: [ - environmentsMixin, - ], - - data() { - const environmentsData = document.querySelector('#environments-folder-list-view').dataset; - const store = new EnvironmentsStore(); - const pathname = window.location.pathname; - const endpoint = `${pathname}.json`; - const folderName = pathname.substr(pathname.lastIndexOf('/') + 1); - - return { - store, - folderName, - endpoint, - state: store.state, - visibility: 'available', - isLoading: false, - cssContainerClass: environmentsData.cssClass, - canCreateDeployment: environmentsData.canCreateDeployment, - canReadEnvironment: environmentsData.canReadEnvironment, - // Pagination Properties, - paginationInformation: {}, - pageNumber: 1, - }; - }, - - computed: { - scope() { - return getParameterByName('scope'); - }, - - canReadEnvironmentParsed() { - return convertPermissionToBoolean(this.canReadEnvironment); - }, - - canCreateDeploymentParsed() { - return convertPermissionToBoolean(this.canCreateDeployment); - }, - - /** - * URL to link in the stopped tab. - * - * @return {String} - */ - stoppedPath() { - return `${window.location.pathname}?scope=stopped`; - }, - - /** - * URL to link in the available tab. - * - * @return {String} - */ - availablePath() { - return window.location.pathname; - }, - }, - - /** - * Fetches all the environments and stores them. - * Toggles loading property. - */ - created() { - const scope = getParameterByName('scope') || this.visibility; - const page = getParameterByName('page') || this.pageNumber; - - this.service = new EnvironmentsService(this.endpoint); - - const poll = new Poll({ - resource: this.service, - method: 'get', - data: { scope, page }, - successCallback: this.successCallback, - errorCallback: this.errorCallback, - notificationCallback: (isMakingRequest) => { - this.isMakingRequest = isMakingRequest; + import environmentsMixin from '../mixins/environments_mixin'; + import CIPaginationMixin from '../../vue_shared/mixins/ci_pagination_api_mixin'; + + export default { + props: { + endpoint: { + type: String, + required: true, + }, + folderName: { + type: String, + required: true, + }, + cssContainerClass: { + type: String, + required: true, + }, + canCreateDeployment: { + type: Boolean, + required: true, + }, + canReadEnvironment: { + type: Boolean, + required: true, }, - }); - - if (!Visibility.hidden()) { - this.isLoading = true; - poll.makeRequest(); - } - - Visibility.change(() => { - if (!Visibility.hidden()) { - poll.restart(); - } else { - poll.stop(); - } - }); - - eventHub.$on('postAction', this.postAction); - }, - - beforeDestroyed() { - eventHub.$off('postAction'); - }, - - methods: { - /** - * Will change the page number and update the URL. - * - * @param {Number} pageNumber desired page to go to. - */ - changePage(pageNumber) { - const param = setParamInURL('page', pageNumber); - - gl.utils.visitUrl(param); - return param; - }, - - fetchEnvironments() { - const scope = getParameterByName('scope') || this.visibility; - const page = getParameterByName('page') || this.pageNumber; - - this.isLoading = true; - - return this.service.get({ scope, page }) - .then(this.successCallback) - .catch(this.errorCallback); - }, - - successCallback(resp) { - this.saveData(resp); - }, - - errorCallback() { - this.isLoading = false; - // eslint-disable-next-line no-new - new Flash('An error occurred while fetching the environments.'); }, - - postAction(endpoint) { - if (!this.isMakingRequest) { - this.isLoading = true; - - this.service.postAction(endpoint) - .then(() => this.fetchEnvironments()) - .catch(() => new Flash('An error occurred while making the request.')); - } + mixins: [ + environmentsMixin, + CIPaginationMixin, + ], + methods: { + successCallback(resp) { + this.saveData(resp); + }, }, - }, -}; + }; </script> <template> <div :class="cssContainerClass"> @@ -171,56 +43,23 @@ export default { v-if="!isLoading"> <h4 class="js-folder-name environments-folder-name"> - Environments / <b>{{folderName}}</b> + {{s__("Environments|Environments")}} / <b>{{folderName}}</b> </h4> - <ul class="nav-links"> - <li :class="{ active: scope === null || scope === 'available' }"> - <a - :href="availablePath" - class="js-available-environments-folder-tab"> - Available - <span class="badge js-available-environments-count"> - {{state.availableCounter}} - </span> - </a> - </li> - <li :class="{ active : scope === 'stopped' }"> - <a - :href="stoppedPath" - class="js-stopped-environments-folder-tab"> - Stopped - <span class="badge js-stopped-environments-count"> - {{state.stoppedCounter}} - </span> - </a> - </li> - </ul> - </div> - - <div class="environments-container"> - - <loading-icon - label="Loading environments" - v-if="isLoading" - size="3" + <tabs + :tabs="tabs" + @onChangeTab="onChangeTab" + scope="environments" /> - - <div - class="table-holder" - v-if="!isLoading && state.environments.length > 0"> - - <environment-table - :environments="state.environments" - :can-create-deployment="canCreateDeploymentParsed" - :can-read-environment="canReadEnvironmentParsed" - /> - - <table-pagination - v-if="state.paginationInformation && state.paginationInformation.totalPages > 1" - :change="changePage" - :pageInfo="state.paginationInformation"/> - </div> </div> + + <container + :is-loading="isLoading" + :environments="state.environments" + :pagination="state.paginationInformation" + :can-create-deployment="canCreateDeployment" + :can-read-environment="canReadEnvironment" + @onChangePage="onChangePage" + /> </div> </template> diff --git a/app/assets/javascripts/environments/mixins/environments_mixin.js b/app/assets/javascripts/environments/mixins/environments_mixin.js index 8f4066e3a6e..7219b076721 100644 --- a/app/assets/javascripts/environments/mixins/environments_mixin.js +++ b/app/assets/javascripts/environments/mixins/environments_mixin.js @@ -1,15 +1,174 @@ +/** + * Common code between environmets app and folder view + */ + +import Visibility from 'visibilityjs'; +import Poll from '../../lib/utils/poll'; +import { + getParameterByName, + parseQueryStringIntoObject, +} from '../../lib/utils/common_utils'; +import { s__ } from '../../locale'; +import Flash from '../../flash'; +import eventHub from '../event_hub'; + +import EnvironmentsStore from '../stores/environments_store'; +import EnvironmentsService from '../services/environments_service'; +import loadingIcon from '../../vue_shared/components/loading_icon.vue'; +import tablePagination from '../../vue_shared/components/table_pagination.vue'; +import environmentTable from '../components/environments_table.vue'; +import tabs from '../../vue_shared/components/navigation_tabs.vue'; +import container from '../components/container.vue'; + export default { + + components: { + environmentTable, + container, + loadingIcon, + tabs, + tablePagination, + }, + + data() { + const store = new EnvironmentsStore(); + + return { + store, + state: store.state, + isLoading: false, + isMakingRequest: false, + scope: getParameterByName('scope') || 'available', + page: getParameterByName('page') || '1', + requestData: {}, + }; + }, + methods: { saveData(resp) { const headers = resp.headers; return resp.json().then((response) => { this.isLoading = false; - this.store.storeAvailableCount(response.available_count); - this.store.storeStoppedCount(response.stopped_count); - this.store.storeEnvironments(response.environments); - this.store.setPagination(headers); + if (_.isEqual(parseQueryStringIntoObject(resp.url.split('?')[1]), this.requestData)) { + this.store.storeAvailableCount(response.available_count); + this.store.storeStoppedCount(response.stopped_count); + this.store.storeEnvironments(response.environments); + this.store.setPagination(headers); + } }); }, + + /** + * Handles URL and query parameter changes. + * When the user uses the pagination or the tabs, + * - update URL + * - Make API request to the server with new parameters + * - Update the polling function + * - Update the internal state + */ + updateContent(parameters) { + this.updateInternalState(parameters); + // fetch new data + return this.service.get(this.requestData) + .then(response => this.successCallback(response)) + .then(() => { + // restart polling + this.poll.restart({ data: this.requestData }); + }) + .catch(() => { + this.errorCallback(); + + // restart polling + this.poll.restart(); + }); + }, + + errorCallback() { + this.isLoading = false; + Flash(s__('Environments|An error occurred while fetching the environments.')); + }, + + postAction(endpoint) { + if (!this.isMakingRequest) { + this.isLoading = true; + + this.service.postAction(endpoint) + .then(() => this.fetchEnvironments()) + .catch(() => { + this.isLoading = false; + Flash(s__('Environments|An error occurred while making the request.')); + }); + } + }, + + fetchEnvironments() { + this.isLoading = true; + + return this.service.get(this.requestData) + .then(this.successCallback) + .catch(this.errorCallback); + }, + + }, + + computed: { + tabs() { + return [ + { + name: s__('Available'), + scope: 'available', + count: this.state.availableCounter, + isActive: this.scope === 'available', + }, + { + name: s__('Stopped'), + scope: 'stopped', + count: this.state.stoppedCounter, + isActive: this.scope === 'stopped', + }, + ]; + }, + }, + + /** + * Fetches all the environments and stores them. + * Toggles loading property. + */ + created() { + this.service = new EnvironmentsService(this.endpoint); + this.requestData = { page: this.page, scope: this.scope }; + + this.poll = new Poll({ + resource: this.service, + method: 'get', + data: this.requestData, + successCallback: this.successCallback, + errorCallback: this.errorCallback, + notificationCallback: (isMakingRequest) => { + this.isMakingRequest = isMakingRequest; + }, + }); + + if (!Visibility.hidden()) { + this.isLoading = true; + this.poll.makeRequest(); + } else { + this.fetchEnvironments(); + } + + Visibility.change(() => { + if (!Visibility.hidden()) { + this.poll.restart(); + } else { + this.poll.stop(); + } + }); + + eventHub.$on('postAction', this.postAction); + }, + + beforeDestroyed() { + eventHub.$off('postAction'); }, }; diff --git a/app/assets/javascripts/environments/stores/environments_store.js b/app/assets/javascripts/environments/stores/environments_store.js index aff8227c38c..5f2989ab854 100644 --- a/app/assets/javascripts/environments/stores/environments_store.js +++ b/app/assets/javascripts/environments/stores/environments_store.js @@ -36,7 +36,12 @@ export default class EnvironmentsStore { storeEnvironments(environments = []) { const filteredEnvironments = environments.map((env) => { const oldEnvironmentState = this.state.environments - .find(element => element.id === env.latest.id) || {}; + .find((element) => { + if (env.latest) { + return element.id === env.latest.id; + } + return element.id === env.id; + }) || {}; let filtered = {}; diff --git a/app/assets/javascripts/groups/components/item_actions.vue b/app/assets/javascripts/groups/components/item_actions.vue index 7eff19e2e5a..09cb79c1afd 100644 --- a/app/assets/javascripts/groups/components/item_actions.vue +++ b/app/assets/javascripts/groups/components/item_actions.vue @@ -4,9 +4,11 @@ import tooltip from '../../vue_shared/directives/tooltip'; import PopupDialog from '../../vue_shared/components/popup_dialog.vue'; import eventHub from '../event_hub'; import { COMMON_STR } from '../constants'; +import Icon from '../../vue_shared/components/icon.vue'; export default { components: { + Icon, PopupDialog, }, directives: { @@ -63,9 +65,9 @@ export default { :aria-label="editBtnTitle" data-container="body" class="edit-group btn no-expand"> - <i - class="fa fa-cogs" - aria-hidden="true"/> + <icon + name="settings"> + </icon> </a> <a v-tooltip diff --git a/app/assets/javascripts/lib/utils/common_utils.js b/app/assets/javascripts/lib/utils/common_utils.js index 195e2ca6a78..6fa1e84c170 100644 --- a/app/assets/javascripts/lib/utils/common_utils.js +++ b/app/assets/javascripts/lib/utils/common_utils.js @@ -270,46 +270,6 @@ export const parseIntPagination = paginationInformation => ({ }); /** - * Updates the search parameter of a URL given the parameter and value provided. - * - * If no search params are present we'll add it. - * If param for page is already present, we'll update it - * If there are params but not for the given one, we'll add it at the end. - * Returns the new search parameters. - * - * @param {String} param - * @param {Number|String|Undefined|Null} value - * @return {String} - */ -export const setParamInURL = (param, value) => { - let search; - const locationSearch = window.location.search; - - if (locationSearch.length) { - const parameters = locationSearch.substring(1, locationSearch.length) - .split('&') - .reduce((acc, element) => { - const val = element.split('='); - // eslint-disable-next-line no-param-reassign - acc[val[0]] = decodeURIComponent(val[1]); - return acc; - }, {}); - - parameters[param] = value; - - const toString = Object.keys(parameters) - .map(val => `${val}=${encodeURIComponent(parameters[val])}`) - .join('&'); - - search = `?${toString}`; - } else { - search = `?${param}=${value}`; - } - - return search; -}; - -/** * Given a string of query parameters creates an object. * * @example diff --git a/app/assets/javascripts/pipelines/components/pipelines.vue b/app/assets/javascripts/pipelines/components/pipelines.vue index 233be8a49c8..fe1f3b4246a 100644 --- a/app/assets/javascripts/pipelines/components/pipelines.vue +++ b/app/assets/javascripts/pipelines/components/pipelines.vue @@ -3,15 +3,14 @@ import PipelinesService from '../services/pipelines_service'; import pipelinesMixin from '../mixins/pipelines'; import tablePagination from '../../vue_shared/components/table_pagination.vue'; - import navigationTabs from './navigation_tabs.vue'; + import navigationTabs from '../../vue_shared/components/navigation_tabs.vue'; import navigationControls from './nav_controls.vue'; import { convertPermissionToBoolean, getParameterByName, - historyPushState, - buildUrlWithCurrentLocation, parseQueryStringIntoObject, } from '../../lib/utils/common_utils'; + import CIPaginationMixin from '../../vue_shared/mixins/ci_pagination_api_mixin'; export default { props: { @@ -36,6 +35,7 @@ }, mixins: [ pipelinesMixin, + CIPaginationMixin, ], data() { const pipelinesData = document.querySelector('#pipelines-list-vue').dataset; @@ -170,22 +170,8 @@ * - Update the internal state */ updateContent(parameters) { - // stop polling - this.poll.stop(); + this.updateInternalState(parameters); - const queryString = Object.keys(parameters).map((parameter) => { - const value = parameters[parameter]; - // update internal state for UI - this[parameter] = value; - return `${parameter}=${encodeURIComponent(value)}`; - }).join('&'); - - // update polling parameters - this.requestData = parameters; - - historyPushState(buildUrlWithCurrentLocation(`?${queryString}`)); - - this.isLoading = true; // fetch new data return this.service.getPipelines(this.requestData) .then((response) => { @@ -203,14 +189,6 @@ this.poll.restart(); }); }, - - onChangeTab(scope) { - this.updateContent({ scope, page: '1' }); - }, - onChangePage(page) { - /* URLS parameters are strings, we need to parse to match types */ - this.updateContent({ scope: this.scope, page: Number(page).toString() }); - }, }, }; </script> @@ -235,6 +213,7 @@ <navigation-tabs :tabs="tabs" @onChangeTab="onChangeTab" + scope="pipelines" /> <navigation-controls diff --git a/app/assets/javascripts/star.js b/app/assets/javascripts/star.js index 1a8dc085772..d5606e153f6 100644 --- a/app/assets/javascripts/star.js +++ b/app/assets/javascripts/star.js @@ -1,5 +1,6 @@ import Flash from './flash'; import { __, s__ } from './locale'; +import { spriteIcon } from './lib/utils/common_utils'; export default class Star { constructor() { @@ -7,16 +8,18 @@ export default class Star { .on('ajax:success', function handleSuccess(e, data) { const $this = $(this); const $starSpan = $this.find('span'); - const $starIcon = $this.find('i'); + const $startIcon = $this.find('svg'); function toggleStar(isStarred) { $this.parent().find('.star-count').text(data.star_count); if (isStarred) { $starSpan.removeClass('starred').text(s__('StarProject|Star')); - $starIcon.removeClass('fa-star').addClass('fa-star-o'); + $startIcon.remove(); + $this.prepend(spriteIcon('star-o')); } else { $starSpan.addClass('starred').text(__('Unstar')); - $starIcon.removeClass('fa-star-o').addClass('fa-star'); + $startIcon.remove(); + $this.prepend(spriteIcon('star')); } } diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_status_icon.js b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_status_icon.js index 4998a47b691..eeb990908f6 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_status_icon.js +++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_status_icon.js @@ -14,7 +14,7 @@ export default { statusObj() { return { group: this.status, - icon: `icon_status_${this.status}`, + icon: `status_${this.status}`, }; }, }, diff --git a/app/assets/javascripts/pipelines/components/navigation_tabs.vue b/app/assets/javascripts/vue_shared/components/navigation_tabs.vue index 07befd23500..a2ddd565170 100644 --- a/app/assets/javascripts/pipelines/components/navigation_tabs.vue +++ b/app/assets/javascripts/vue_shared/components/navigation_tabs.vue @@ -1,11 +1,36 @@ <script> + /** + * Given an array of tabs, renders non linked bootstrap tabs. + * When a tab is clicked it will trigger an event and provide the clicked scope. + * + * This component is used in apps that handle the API call. + * If you only need to change the URL this component should not be used. + * + * @example + * <navigation-tabs + * :tabs="[ + * { + * name: String, + * scope: String, + * count: Number || Undefined, + * isActive: Boolean, + * }, + * ]" + * @onChangeTab="onChangeTab" + * /> + */ export default { - name: 'PipelineNavigationTabs', + name: 'NavigationTabs', props: { tabs: { type: Array, required: true, }, + scope: { + type: String, + required: false, + default: '', + }, }, mounted() { $(document).trigger('init.scrolling-tabs'); @@ -34,7 +59,7 @@ <a role="button" @click="onTabClick(tab)" - :class="`js-pipelines-tab-${tab.scope}`" + :class="`js-${scope}-tab-${tab.scope}`" > {{ tab.name }} diff --git a/app/assets/javascripts/vue_shared/mixins/ci_pagination_api_mixin.js b/app/assets/javascripts/vue_shared/mixins/ci_pagination_api_mixin.js new file mode 100644 index 00000000000..f94cc670edf --- /dev/null +++ b/app/assets/javascripts/vue_shared/mixins/ci_pagination_api_mixin.js @@ -0,0 +1,42 @@ +/** + * API callbacks for pagination and tabs + * shared between Pipelines and Environments table. + * + * Components need to have `scope`, `page` and `requestData` + */ +import { + historyPushState, + buildUrlWithCurrentLocation, +} from '../../lib/utils/common_utils'; + +export default { + methods: { + onChangeTab(scope) { + this.updateContent({ scope, page: '1' }); + }, + + onChangePage(page) { + /* URLS parameters are strings, we need to parse to match types */ + this.updateContent({ scope: this.scope, page: Number(page).toString() }); + }, + + updateInternalState(parameters) { + // stop polling + this.poll.stop(); + + const queryString = Object.keys(parameters).map((parameter) => { + const value = parameters[parameter]; + // update internal state for UI + this[parameter] = value; + return `${parameter}=${encodeURIComponent(value)}`; + }).join('&'); + + // update polling parameters + this.requestData = parameters; + + historyPushState(buildUrlWithCurrentLocation(`?${queryString}`)); + + this.isLoading = true; + }, + }, +}; diff --git a/app/assets/stylesheets/framework/files.scss b/app/assets/stylesheets/framework/files.scss index c2a3cd16e67..609f33582e1 100644 --- a/app/assets/stylesheets/framework/files.scss +++ b/app/assets/stylesheets/framework/files.scss @@ -364,6 +364,18 @@ span.idiff { float: none; } } + + @media (max-width: $screen-xs-max) { + display: block; + + .file-actions { + white-space: normal; + + .btn-group { + padding-top: 5px; + } + } + } } .is-stl-loading { diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index b2ec491146f..ee21d81f23e 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -196,7 +196,7 @@ class ApplicationController < ActionController::Base end def check_password_expiration - return if session[:impersonator_id] || current_user&.ldap_user? + return if session[:impersonator_id] || !current_user&.allow_password_authentication? password_expires_at = current_user&.password_expires_at diff --git a/app/controllers/concerns/issuable_collections.rb b/app/controllers/concerns/issuable_collections.rb index 2b011bc87b0..f3c9251225f 100644 --- a/app/controllers/concerns/issuable_collections.rb +++ b/app/controllers/concerns/issuable_collections.rb @@ -150,7 +150,7 @@ module IssuableCollections when 'MergeRequest' [ :source_project, :target_project, :author, :assignee, :labels, :milestone, - head_pipeline: :project, target_project: :namespace, merge_request_diff: :merge_request_diff_commits + head_pipeline: :project, target_project: :namespace, latest_merge_request_diff: :merge_request_diff_commits ] end end diff --git a/app/controllers/concerns/preview_markdown.rb b/app/controllers/concerns/preview_markdown.rb index 5ce602b55a8..e9b9e9b38bc 100644 --- a/app/controllers/concerns/preview_markdown.rb +++ b/app/controllers/concerns/preview_markdown.rb @@ -8,6 +8,7 @@ module PreviewMarkdown case controller_name when 'wikis' then { pipeline: :wiki, project_wiki: @project_wiki, page_slug: params[:id] } when 'snippets' then { skip_project_check: true } + when 'groups' then { group: group } else {} end diff --git a/app/controllers/invites_controller.rb b/app/controllers/invites_controller.rb index 0982a61902b..04b29aa2384 100644 --- a/app/controllers/invites_controller.rb +++ b/app/controllers/invites_controller.rb @@ -51,7 +51,7 @@ class InvitesController < ApplicationController return if current_user notice = "To accept this invitation, sign in" - notice << " or create an account" if current_application_settings.signup_enabled? + notice << " or create an account" if current_application_settings.allow_signup? notice << "." store_location_for :user, request.fullpath diff --git a/app/controllers/omniauth_callbacks_controller.rb b/app/controllers/omniauth_callbacks_controller.rb index 56baa19f864..e3c18cba1dd 100644 --- a/app/controllers/omniauth_callbacks_controller.rb +++ b/app/controllers/omniauth_callbacks_controller.rb @@ -140,7 +140,7 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController label = Gitlab::OAuth::Provider.label_for(oauth['provider']) message = "Signing in using your #{label} account without a pre-existing GitLab account is not allowed." - if current_application_settings.signup_enabled? + if current_application_settings.allow_signup? message << " Create a GitLab account first, and then connect it to your #{label} account." end diff --git a/app/controllers/passwords_controller.rb b/app/controllers/passwords_controller.rb index fda944adecd..68a52f40342 100644 --- a/app/controllers/passwords_controller.rb +++ b/app/controllers/passwords_controller.rb @@ -1,6 +1,8 @@ class PasswordsController < Devise::PasswordsController + include Gitlab::CurrentSettings + before_action :resource_from_email, only: [:create] - before_action :prevent_ldap_reset, only: [:create] + before_action :check_password_authentication_available, only: [:create] before_action :throttle_reset, only: [:create] def edit @@ -25,7 +27,7 @@ class PasswordsController < Devise::PasswordsController def update super do |resource| - if resource.valid? && resource.require_password_creation? + if resource.valid? && resource.password_automatically_set? resource.update_attribute(:password_automatically_set, false) end end @@ -38,11 +40,15 @@ class PasswordsController < Devise::PasswordsController self.resource = resource_class.find_by_email(email) end - def prevent_ldap_reset - return unless resource&.ldap_user? + def check_password_authentication_available + if resource + return if resource.allow_password_authentication? + else + return if current_application_settings.password_authentication_enabled? + end redirect_to after_sending_reset_password_instructions_path_for(resource_name), - alert: "Cannot reset password for LDAP user." + alert: "Password authentication is unavailable." end def throttle_reset diff --git a/app/controllers/profiles/passwords_controller.rb b/app/controllers/profiles/passwords_controller.rb index dcfcb855ab5..fa72f67c77e 100644 --- a/app/controllers/profiles/passwords_controller.rb +++ b/app/controllers/profiles/passwords_controller.rb @@ -77,7 +77,7 @@ class Profiles::PasswordsController < Profiles::ApplicationController end def authorize_change_password! - render_404 if @user.ldap_user? + render_404 unless @user.allow_password_authentication? end def user_params diff --git a/app/controllers/projects/environments_controller.rb b/app/controllers/projects/environments_controller.rb index 29e223a5273..52d528e816e 100644 --- a/app/controllers/projects/environments_controller.rb +++ b/app/controllers/projects/environments_controller.rb @@ -34,6 +34,7 @@ class Projects::EnvironmentsController < Projects::ApplicationController folder_environments = project.environments.where(environment_type: params[:id]) @environments = folder_environments.with_state(params[:scope] || :available) .order(:name) + @folder = params[:id] respond_to do |format| format.html diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb index c01be42c3ee..d79108c88fb 100644 --- a/app/controllers/sessions_controller.rb +++ b/app/controllers/sessions_controller.rb @@ -63,7 +63,7 @@ class SessionsController < Devise::SessionsController user = User.admins.last - return unless user && user.require_password_creation? + return unless user && user.require_password_creation_for_web? Users::UpdateService.new(current_user, user: user).execute do |user| @token = user.generate_reset_token diff --git a/app/controllers/unicorn_test_controller.rb b/app/controllers/unicorn_test_controller.rb deleted file mode 100644 index ed04bd1f77d..00000000000 --- a/app/controllers/unicorn_test_controller.rb +++ /dev/null @@ -1,14 +0,0 @@ -# :nocov: -if Rails.env.test? - class UnicornTestController < ActionController::Base - def pid - render plain: Process.pid.to_s - end - - def kill - Process.kill(params[:signal], Process.pid) - render plain: 'Bye!' - end - end -end -# :nocov: diff --git a/app/helpers/application_settings_helper.rb b/app/helpers/application_settings_helper.rb index e5d2693b01e..6fc4248b245 100644 --- a/app/helpers/application_settings_helper.rb +++ b/app/helpers/application_settings_helper.rb @@ -3,9 +3,9 @@ module ApplicationSettingsHelper include Gitlab::CurrentSettings - delegate :gravatar_enabled?, - :signup_enabled?, - :password_authentication_enabled?, + delegate :allow_signup?, + :gravatar_enabled?, + :password_authentication_enabled_for_web?, :akismet_enabled?, :koding_enabled?, to: :current_application_settings @@ -203,7 +203,7 @@ module ApplicationSettingsHelper :metrics_port, :metrics_sample_interval, :metrics_timeout, - :password_authentication_enabled, + :password_authentication_enabled_for_web, :performance_bar_allowed_group_id, :performance_bar_enabled, :plantuml_enabled, diff --git a/app/helpers/button_helper.rb b/app/helpers/button_helper.rb index 48cf30a48ab..8e8feeea1d8 100644 --- a/app/helpers/button_helper.rb +++ b/app/helpers/button_helper.rb @@ -58,12 +58,12 @@ module ButtonHelper def http_clone_button(project, placement = 'right', append_link: true) klass = 'http-selector' - klass << ' has-tooltip' if current_user.try(:require_password_creation?) || current_user.try(:require_personal_access_token_creation_for_git_auth?) + klass << ' has-tooltip' if current_user.try(:require_extra_setup_for_git_auth?) protocol = gitlab_config.protocol.upcase tooltip_title = - if current_user.try(:require_password_creation?) + if current_user.try(:require_password_creation_for_git?) _("Set a password on your account to pull or push via %{protocol}.") % { protocol: protocol } else _("Create a personal access token on your account to pull or push via %{protocol}.") % { protocol: protocol } diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index f48d47953e4..4a6b22b5ff6 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -234,11 +234,11 @@ module ProjectsHelper def show_no_password_message? cookies[:hide_no_password_message].blank? && !current_user.hide_no_password && - ( current_user.require_password_creation? || current_user.require_personal_access_token_creation_for_git_auth? ) + current_user.require_extra_setup_for_git_auth? end def link_to_set_password - if current_user.require_password_creation? + if current_user.require_password_creation_for_git? link_to s_('SetPasswordToCloneLink|set a password'), edit_profile_password_path else link_to s_('CreateTokenToCloneLink|create a personal access token'), profile_personal_access_tokens_path diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb index a7e0219b03a..01455a52d2a 100644 --- a/app/models/application_setting.rb +++ b/app/models/application_setting.rb @@ -276,7 +276,8 @@ class ApplicationSetting < ActiveRecord::Base koding_url: nil, max_artifacts_size: Settings.artifacts['max_size'], max_attachment_size: Settings.gitlab['max_attachment_size'], - password_authentication_enabled: Settings.gitlab['password_authentication_enabled'], + password_authentication_enabled_for_web: Settings.gitlab['signin_enabled'], + password_authentication_enabled_for_git: true, performance_bar_allowed_group_id: nil, rsa_key_restriction: 0, plantuml_enabled: false, @@ -474,6 +475,14 @@ class ApplicationSetting < ActiveRecord::Base has_attribute?(attr_name) ? public_send(attr_name) : FORBIDDEN_KEY_VALUE # rubocop:disable GitlabSecurity/PublicSend end + def allow_signup? + signup_enabled? && password_authentication_enabled_for_web? + end + + def password_authentication_enabled? + password_authentication_enabled_for_web? || password_authentication_enabled_for_git? + end + private def ensure_uuid! diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index 1d9f367183e..1e9a3920667 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -243,7 +243,7 @@ module Ci @merge_request ||= begin - merge_requests = MergeRequest.includes(:merge_request_diff) + merge_requests = MergeRequest.includes(:latest_merge_request_diff) .where(source_branch: ref, source_project: pipeline.project) .reorder(iid: :desc) diff --git a/app/models/commit.rb b/app/models/commit.rb index 8401d99a08f..6b28d290f99 100644 --- a/app/models/commit.rb +++ b/app/models/commit.rb @@ -109,12 +109,12 @@ class Commit @link_reference_pattern ||= super("commit", /(?<commit>#{COMMIT_SHA_PATTERN})/) end - def to_reference(from_project = nil, full: false) - commit_reference(from_project, id, full: full) + def to_reference(from = nil, full: false) + commit_reference(from, id, full: full) end - def reference_link_text(from_project = nil, full: false) - commit_reference(from_project, short_id, full: full) + def reference_link_text(from = nil, full: false) + commit_reference(from, short_id, full: full) end def diff_line_count @@ -381,8 +381,8 @@ class Commit private - def commit_reference(from_project, referable_commit_id, full: false) - reference = project.to_reference(from_project, full: full) + def commit_reference(from, referable_commit_id, full: false) + reference = project.to_reference(from, full: full) if reference.present? "#{reference}#{self.class.reference_prefix}#{referable_commit_id}" diff --git a/app/models/commit_range.rb b/app/models/commit_range.rb index 84e2e8a5dd5..b93c111dabc 100644 --- a/app/models/commit_range.rb +++ b/app/models/commit_range.rb @@ -89,8 +89,8 @@ class CommitRange alias_method :id, :to_s - def to_reference(from_project = nil, full: false) - project_reference = project.to_reference(from_project, full: full) + def to_reference(from = nil, full: false) + project_reference = project.to_reference(from, full: full) if project_reference.present? project_reference + self.class.reference_prefix + self.id @@ -99,8 +99,8 @@ class CommitRange end end - def reference_link_text(from_project = nil) - project_reference = project.to_reference(from_project) + def reference_link_text(from = nil) + project_reference = project.to_reference(from) reference = ref_from + notation + ref_to if project_reference.present? diff --git a/app/models/concerns/manual_inverse_association.rb b/app/models/concerns/manual_inverse_association.rb new file mode 100644 index 00000000000..0fca8feaf89 --- /dev/null +++ b/app/models/concerns/manual_inverse_association.rb @@ -0,0 +1,17 @@ +module ManualInverseAssociation + extend ActiveSupport::Concern + + module ClassMethods + def manual_inverse_association(association, inverse) + define_method(association) do |*args| + super(*args).tap do |value| + next unless value + + child_association = value.association(inverse) + child_association.set_inverse_instance(self) + child_association.target = self + end + end + end + end +end diff --git a/app/models/concerns/mentionable.rb b/app/models/concerns/mentionable.rb index 1db6b2d2fa2..b43eaeaeea0 100644 --- a/app/models/concerns/mentionable.rb +++ b/app/models/concerns/mentionable.rb @@ -31,11 +31,11 @@ module Mentionable # # By default this will be the class name and the result of calling # `to_reference` on the object. - def gfm_reference(from_project = nil) + def gfm_reference(from = nil) # "MergeRequest" > "merge_request" > "Merge request" > "merge request" friendly_name = self.class.to_s.underscore.humanize.downcase - "#{friendly_name} #{to_reference(from_project)}" + "#{friendly_name} #{to_reference(from)}" end # The GFM reference to this Mentionable, which shouldn't be included in its #references. diff --git a/app/models/concerns/referable.rb b/app/models/concerns/referable.rb index 78ac4f324e7..b782e85717e 100644 --- a/app/models/concerns/referable.rb +++ b/app/models/concerns/referable.rb @@ -7,7 +7,7 @@ module Referable # Returns the String necessary to reference this object in Markdown # - # from_project - Refering Project object + # from - Referring parent object # # This should be overridden by the including class. # @@ -17,12 +17,12 @@ module Referable # Issue.last.to_reference(other_project) # => "cross-project#1" # # Returns a String - def to_reference(_from_project = nil, full:) + def to_reference(_from = nil, full:) '' end - def reference_link_text(from_project = nil) - to_reference(from_project) + def reference_link_text(from = nil) + to_reference(from) end included do diff --git a/app/models/external_issue.rb b/app/models/external_issue.rb index 9ff56f229bc..2aaba2e4c90 100644 --- a/app/models/external_issue.rb +++ b/app/models/external_issue.rb @@ -38,11 +38,11 @@ class ExternalIssue @project.id end - def to_reference(_from_project = nil, full: nil) + def to_reference(_from = nil, full: nil) id end - def reference_link_text(from_project = nil) + def reference_link_text(from = nil) return "##{id}" if id =~ /^\d+$/ id diff --git a/app/models/group.rb b/app/models/group.rb index 8cf632fb566..dc4500360b9 100644 --- a/app/models/group.rb +++ b/app/models/group.rb @@ -97,7 +97,7 @@ class Group < Namespace end end - def to_reference(_from_project = nil, full: nil) + def to_reference(_from = nil, full: nil) "#{self.class.reference_prefix}#{full_path}" end diff --git a/app/models/label.rb b/app/models/label.rb index 899028a01a0..b5bfa6ea2dd 100644 --- a/app/models/label.rb +++ b/app/models/label.rb @@ -165,12 +165,12 @@ class Label < ActiveRecord::Base # # Returns a String # - def to_reference(from_project = nil, target_project: nil, format: :id, full: false) + def to_reference(from = nil, target_project: nil, format: :id, full: false) format_reference = label_format_reference(format) reference = "#{self.class.reference_prefix}#{format_reference}" - if from_project - "#{from_project.to_reference(target_project, full: full)}#{reference}" + if from + "#{from.to_reference(target_project, full: full)}#{reference}" else reference end diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index f1a5cc73e83..5cf41b2c7cb 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -5,6 +5,8 @@ class MergeRequest < ActiveRecord::Base include Referable include IgnorableColumn include TimeTrackable + include ManualInverseAssociation + include EachBatch ignore_column :locked_at, :ref_fetched @@ -14,9 +16,28 @@ class MergeRequest < ActiveRecord::Base belongs_to :merge_user, class_name: "User" has_many :merge_request_diffs + has_one :merge_request_diff, -> { order('merge_request_diffs.id DESC') }, inverse_of: :merge_request + belongs_to :latest_merge_request_diff, class_name: 'MergeRequestDiff' + manual_inverse_association :latest_merge_request_diff, :merge_request + + # This is the same as latest_merge_request_diff unless: + # 1. There are arguments - in which case we might be trying to force-reload. + # 2. This association is already loaded. + # 3. The latest diff does not exist. + # + # The second one in particular is important - MergeRequestDiff#merge_request + # is the inverse of MergeRequest#merge_request_diff, which means it may not be + # the latest diff, because we could have loaded any diff from this particular + # MR. If we haven't already loaded a diff, then it's fine to load the latest. + def merge_request_diff(*args) + fallback = latest_merge_request_diff if args.empty? && !association(:merge_request_diff).loaded? + + fallback || super + end + belongs_to :head_pipeline, foreign_key: "head_pipeline_id", class_name: "Ci::Pipeline" has_many :events, as: :target, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent @@ -167,6 +188,22 @@ class MergeRequest < ActiveRecord::Base where("merge_requests.id IN (#{union.to_sql})") # rubocop:disable GitlabSecurity/SqlInjection end + # This is used after project import, to reset the IDs to the correct + # values. It is not intended to be called without having already scoped the + # relation. + def self.set_latest_merge_request_diff_ids! + update = ' + latest_merge_request_diff_id = ( + SELECT MAX(id) + FROM merge_request_diffs + WHERE merge_requests.id = merge_request_diffs.merge_request_id + )'.squish + + self.each_batch do |batch| + batch.update_all(update) + end + end + WIP_REGEX = /\A\s*(\[WIP\]\s*|WIP:\s*|WIP\s+)+\s*/i.freeze def self.work_in_progress?(title) diff --git a/app/models/merge_request_diff.rb b/app/models/merge_request_diff.rb index 5382f5cc627..9ee561b5161 100644 --- a/app/models/merge_request_diff.rb +++ b/app/models/merge_request_diff.rb @@ -2,6 +2,7 @@ class MergeRequestDiff < ActiveRecord::Base include Sortable include Importable include Gitlab::EncodingHelper + include ManualInverseAssociation # Prevent store of diff if commits amount more then 500 COMMITS_SAFE_SIZE = 100 @@ -10,6 +11,8 @@ class MergeRequestDiff < ActiveRecord::Base VALID_CLASSES = [Hash, Rugged::Patch, Rugged::Diff::Delta].freeze belongs_to :merge_request + manual_inverse_association :merge_request, :merge_request_diff + has_many :merge_request_diff_files, -> { order(:merge_request_diff_id, :relative_order) } has_many :merge_request_diff_commits, -> { order(:merge_request_diff_id, :relative_order) } @@ -194,7 +197,7 @@ class MergeRequestDiff < ActiveRecord::Base end def latest? - self == merge_request.merge_request_diff + self.id == merge_request.latest_merge_request_diff_id end def compare_with(sha) diff --git a/app/models/milestone.rb b/app/models/milestone.rb index e01e52131f0..01458120cda 100644 --- a/app/models/milestone.rb +++ b/app/models/milestone.rb @@ -162,18 +162,18 @@ class Milestone < ActiveRecord::Base # Milestone.first.to_reference(cross_namespace_project) # => "gitlab-org/gitlab-ce%1" # Milestone.first.to_reference(same_namespace_project) # => "gitlab-ce%1" # - def to_reference(from_project = nil, format: :name, full: false) + def to_reference(from = nil, format: :name, full: false) format_reference = milestone_format_reference(format) reference = "#{self.class.reference_prefix}#{format_reference}" if project - "#{project.to_reference(from_project, full: full)}#{reference}" + "#{project.to_reference(from, full: full)}#{reference}" else reference end end - def reference_link_text(from_project = nil) + def reference_link_text(from = nil) self.title end diff --git a/app/models/project.rb b/app/models/project.rb index 894ded2a9f6..43a4d86c138 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -760,10 +760,10 @@ class Project < ActiveRecord::Base end end - def to_human_reference(from_project = nil) - if cross_namespace_reference?(from_project) + def to_human_reference(from = nil) + if cross_namespace_reference?(from) name_with_namespace - elsif cross_project_reference?(from_project) + elsif cross_project_reference?(from) name end end diff --git a/app/models/repository.rb b/app/models/repository.rb index 2bf21cbdcc4..d4ffd7bfc07 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -909,19 +909,13 @@ class Repository end end - def merged_to_root_ref?(branch_or_name, pre_loaded_merged_branches = nil) + def merged_to_root_ref?(branch_or_name) branch = Gitlab::Git::Branch.find(self, branch_or_name) if branch @root_ref_sha ||= commit(root_ref).sha same_head = branch.target == @root_ref_sha - merged = - if pre_loaded_merged_branches - pre_loaded_merged_branches.include?(branch.name) - else - ancestor?(branch.target, @root_ref_sha) - end - + merged = ancestor?(branch.target, @root_ref_sha) !same_head && merged else nil diff --git a/app/models/snippet.rb b/app/models/snippet.rb index 9533aa7f555..2a5f07a15c4 100644 --- a/app/models/snippet.rb +++ b/app/models/snippet.rb @@ -75,11 +75,11 @@ class Snippet < ActiveRecord::Base @link_reference_pattern ||= super("snippets", /(?<snippet>\d+)/) end - def to_reference(from_project = nil, full: false) + def to_reference(from = nil, full: false) reference = "#{self.class.reference_prefix}#{id}" if project.present? - "#{project.to_reference(from_project, full: full)}#{reference}" + "#{project.to_reference(from, full: full)}#{reference}" else reference end diff --git a/app/models/user.rb b/app/models/user.rb index f98165754ca..cf6b36559a8 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -437,7 +437,7 @@ class User < ActiveRecord::Base username end - def to_reference(_from_project = nil, target_project: nil, full: nil) + def to_reference(_from = nil, target_project: nil, full: nil) "#{self.class.reference_prefix}#{username}" end @@ -633,18 +633,34 @@ class User < ActiveRecord::Base count.zero? && Gitlab::ProtocolAccess.allowed?('ssh') end - def require_password_creation? - password_automatically_set? && allow_password_authentication? + def require_password_creation_for_web? + allow_password_authentication_for_web? && password_automatically_set? + end + + def require_password_creation_for_git? + allow_password_authentication_for_git? && password_automatically_set? end def require_personal_access_token_creation_for_git_auth? - return false if current_application_settings.password_authentication_enabled? || ldap_user? + return false if allow_password_authentication_for_git? || ldap_user? PersonalAccessTokensFinder.new(user: self, impersonation: false, state: 'active').execute.none? end + def require_extra_setup_for_git_auth? + require_password_creation_for_git? || require_personal_access_token_creation_for_git_auth? + end + def allow_password_authentication? - !ldap_user? && current_application_settings.password_authentication_enabled? + allow_password_authentication_for_web? || allow_password_authentication_for_git? + end + + def allow_password_authentication_for_web? + current_application_settings.password_authentication_enabled_for_web? && !ldap_user? + end + + def allow_password_authentication_for_git? + current_application_settings.password_authentication_enabled_for_git? && !ldap_user? end def can_change_username? diff --git a/app/services/merge_requests/refresh_service.rb b/app/services/merge_requests/refresh_service.rb index fc100580c4f..bf3d4855122 100644 --- a/app/services/merge_requests/refresh_service.rb +++ b/app/services/merge_requests/refresh_service.rb @@ -35,7 +35,7 @@ module MergeRequests # target branch manually def close_merge_requests commit_ids = @commits.map(&:id) - merge_requests = @project.merge_requests.preload(:merge_request_diff).opened.where(target_branch: @branch_name).to_a + merge_requests = @project.merge_requests.preload(:latest_merge_request_diff).opened.where(target_branch: @branch_name).to_a merge_requests = merge_requests.select(&:diff_head_commit) merge_requests = merge_requests.select do |merge_request| diff --git a/app/services/protected_branches/api_create_service.rb b/app/services/protected_branches/legacy_api_create_service.rb index f2040dfa03a..e358fd0374e 100644 --- a/app/services/protected_branches/api_create_service.rb +++ b/app/services/protected_branches/legacy_api_create_service.rb @@ -1,9 +1,9 @@ -# The protected branches API still uses the `developers_can_push` and `developers_can_merge` +# The branches#protect API still uses the `developers_can_push` and `developers_can_merge` # flags for backward compatibility, and so performs translation between that format and the # internal data model (separate access levels). The translation code is non-trivial, and so # lives in this service. module ProtectedBranches - class ApiCreateService < BaseService + class LegacyApiCreateService < BaseService def execute push_access_level = if params.delete(:developers_can_push) diff --git a/app/services/protected_branches/api_update_service.rb b/app/services/protected_branches/legacy_api_update_service.rb index bdb0e0cc8bf..33176253ca2 100644 --- a/app/services/protected_branches/api_update_service.rb +++ b/app/services/protected_branches/legacy_api_update_service.rb @@ -1,9 +1,9 @@ -# The protected branches API still uses the `developers_can_push` and `developers_can_merge` +# The branches#protect API still uses the `developers_can_push` and `developers_can_merge` # flags for backward compatibility, and so performs translation between that format and the # internal data model (separate access levels). The translation code is non-trivial, and so # lives in this service. module ProtectedBranches - class ApiUpdateService < BaseService + class LegacyApiUpdateService < BaseService def execute(protected_branch) @developers_can_push = params.delete(:developers_can_push) @developers_can_merge = params.delete(:developers_can_merge) diff --git a/app/services/users/build_service.rb b/app/services/users/build_service.rb index 6f05500adea..61f1568f366 100644 --- a/app/services/users/build_service.rb +++ b/app/services/users/build_service.rb @@ -34,7 +34,7 @@ module Users private def can_create_user? - (current_user.nil? && current_application_settings.signup_enabled?) || current_user&.admin? + (current_user.nil? && current_application_settings.allow_signup?) || current_user&.admin? end # Allowed params for creating a user (admins only) diff --git a/app/views/admin/application_settings/_form.html.haml b/app/views/admin/application_settings/_form.html.haml index 12658dddc06..64249c91dd0 100644 --- a/app/views/admin/application_settings/_form.html.haml +++ b/app/views/admin/application_settings/_form.html.haml @@ -160,9 +160,22 @@ .form-group .col-sm-offset-2.col-sm-10 .checkbox - = f.label :password_authentication_enabled do - = f.check_box :password_authentication_enabled - Sign-in enabled + = f.label :password_authentication_enabled_for_web do + = f.check_box :password_authentication_enabled_for_web + Password authentication enabled for web interface + .help-block + When disabled, an external authentication provider must be used. + .form-group + .col-sm-offset-2.col-sm-10 + .checkbox + = f.label :password_authentication_enabled_for_git do + = f.check_box :password_authentication_enabled_for_git + Password authentication enabled for Git over HTTP(S) + .help-block + When disabled, a Personal Access Token + - if Gitlab::LDAP::Config.enabled? + or LDAP password + must be used to authenticate. - if omniauth_enabled? && button_based_providers.any? .form-group = f.label :enabled_oauth_sign_in_sources, 'Enabled OAuth sign-in sources', class: 'control-label col-sm-2' diff --git a/app/views/admin/dashboard/index.html.haml b/app/views/admin/dashboard/index.html.haml index 2f0143c7eff..a24516355bf 100644 --- a/app/views/admin/dashboard/index.html.haml +++ b/app/views/admin/dashboard/index.html.haml @@ -45,10 +45,10 @@ .well-segment.admin-well.admin-well-features %h4 Features - sign_up = "Sign up" - %p{ "aria-label" => "#{sign_up}: status " + (signup_enabled? ? "on" : "off") } + %p{ "aria-label" => "#{sign_up}: status " + (allow_signup? ? "on" : "off") } = sign_up %span.light.pull-right - = boolean_to_icon signup_enabled? + = boolean_to_icon allow_signup? - ldap = "LDAP" %p{ "aria-label" => "#{ldap}: status " + (Gitlab.config.ldap.enabled ? "on" : "off") } = ldap diff --git a/app/views/devise/sessions/new.html.haml b/app/views/devise/sessions/new.html.haml index dd61dcf2a7b..34d4293bd45 100644 --- a/app/views/devise/sessions/new.html.haml +++ b/app/views/devise/sessions/new.html.haml @@ -6,15 +6,15 @@ - else = render 'devise/shared/tabs_normal' .tab-content - - if password_authentication_enabled? || ldap_enabled? || crowd_enabled? + - if password_authentication_enabled_for_web? || ldap_enabled? || crowd_enabled? = render 'devise/shared/signin_box' -# Signup only makes sense if you can also sign-in - - if password_authentication_enabled? && signup_enabled? + - if allow_signup? = render 'devise/shared/signup_box' -# Show a message if none of the mechanisms above are enabled - - if !password_authentication_enabled? && !ldap_enabled? && !(omniauth_enabled? && devise_mapping.omniauthable?) + - if !password_authentication_enabled_for_web? && !ldap_enabled? && !(omniauth_enabled? && devise_mapping.omniauthable?) %div No authentication methods configured. diff --git a/app/views/devise/shared/_links.erb b/app/views/devise/shared/_links.erb index 49e99e25c1d..6e1cc244f26 100644 --- a/app/views/devise/shared/_links.erb +++ b/app/views/devise/shared/_links.erb @@ -2,7 +2,7 @@ <%= link_to "Sign in", new_session_path(resource_name), class: "btn" %><br /> <% end -%> -<%- if devise_mapping.registerable? && controller_name != 'registrations' && gitlab_config.signup_enabled %> +<%- if devise_mapping.registerable? && controller_name != 'registrations' && allow_signup? %> <%= link_to "Sign up", new_registration_path(resource_name) %><br /> <% end -%> diff --git a/app/views/devise/shared/_signin_box.html.haml b/app/views/devise/shared/_signin_box.html.haml index 3b06008febe..6087f4a0b37 100644 --- a/app/views/devise/shared/_signin_box.html.haml +++ b/app/views/devise/shared/_signin_box.html.haml @@ -7,12 +7,12 @@ .login-box.tab-pane{ id: "#{server['provider_name']}", role: 'tabpanel', class: active_when(i.zero? && !crowd_enabled?) } .login-body = render 'devise/sessions/new_ldap', server: server - - if password_authentication_enabled? + - if password_authentication_enabled_for_web? .login-box.tab-pane{ id: 'ldap-standard', role: 'tabpanel' } .login-body = render 'devise/sessions/new_base' -- elsif password_authentication_enabled? +- elsif password_authentication_enabled_for_web? .login-box.tab-pane.active{ id: 'login-pane', role: 'tabpanel' } .login-body = render 'devise/sessions/new_base' diff --git a/app/views/devise/shared/_tabs_ldap.html.haml b/app/views/devise/shared/_tabs_ldap.html.haml index 6d0243a325d..94f19ccd44c 100644 --- a/app/views/devise/shared/_tabs_ldap.html.haml +++ b/app/views/devise/shared/_tabs_ldap.html.haml @@ -5,9 +5,9 @@ - @ldap_servers.each_with_index do |server, i| %li{ class: active_when(i.zero? && !crowd_enabled?) } = link_to server['label'], "##{server['provider_name']}", 'data-toggle' => 'tab' - - if password_authentication_enabled? + - if password_authentication_enabled_for_web? %li = link_to 'Standard', '#ldap-standard', 'data-toggle' => 'tab' - - if password_authentication_enabled? && signup_enabled? + - if allow_signup? %li = link_to 'Register', '#register-pane', 'data-toggle' => 'tab' diff --git a/app/views/devise/shared/_tabs_normal.html.haml b/app/views/devise/shared/_tabs_normal.html.haml index 212856c0676..1ba6d390875 100644 --- a/app/views/devise/shared/_tabs_normal.html.haml +++ b/app/views/devise/shared/_tabs_normal.html.haml @@ -1,6 +1,6 @@ %ul.nav-links.new-session-tabs.nav-tabs{ role: 'tablist' } %li.active{ role: 'presentation' } %a{ href: '#login-pane', data: { toggle: 'tab' }, role: 'tab' } Sign in - - if password_authentication_enabled? && signup_enabled? + - if allow_signup? %li{ role: 'presentation' } %a{ href: '#register-pane', data: { toggle: 'tab' }, role: 'tab' } Register diff --git a/app/views/layouts/_mailer.html.haml b/app/views/layouts/_mailer.html.haml index 983ed22a506..b50537438a9 100644 --- a/app/views/layouts/_mailer.html.haml +++ b/app/views/layouts/_mailer.html.haml @@ -10,6 +10,10 @@ body, table, td, a { -webkit-text-size-adjust: 100%; -ms-text-size-adjust: 100%; } table, td { mso-table-lspace: 0pt; mso-table-rspace: 0pt; } img { -ms-interpolation-mode: bicubic; } + .hidden { + display: none !important; + visibility: hidden !important; + } /* iOS BLUE LINKS */ a[x-apple-data-detectors] { diff --git a/app/views/layouts/nav/sidebar/_profile.html.haml b/app/views/layouts/nav/sidebar/_profile.html.haml index 458b5010d36..7e23f9c1f05 100644 --- a/app/views/layouts/nav/sidebar/_profile.html.haml +++ b/app/views/layouts/nav/sidebar/_profile.html.haml @@ -73,7 +73,7 @@ = link_to profile_emails_path do %strong.fly-out-top-item-name #{ _('Emails') } - - unless current_user.ldap_user? + - if current_user.allow_password_authentication? = nav_link(controller: :passwords) do = link_to edit_profile_password_path do .nav-icon-container diff --git a/app/views/notify/new_user_email.html.haml b/app/views/notify/new_user_email.html.haml index 6b9b42dcf37..00e1b5faae3 100644 --- a/app/views/notify/new_user_email.html.haml +++ b/app/views/notify/new_user_email.html.haml @@ -1,7 +1,7 @@ %p Hi #{@user['name']}! %p - - if Gitlab.config.gitlab.signup_enabled + - if current_application_settings.allow_signup? Your account has been created successfully. - else The Administrator created an account for you. Now you are a member of the company GitLab application. diff --git a/app/views/projects/blob/_header.html.haml b/app/views/projects/blob/_header.html.haml index 0be15cc179f..281363d2e01 100644 --- a/app/views/projects/blob/_header.html.haml +++ b/app/views/projects/blob/_header.html.haml @@ -2,7 +2,7 @@ .js-file-title.file-title-flex-parent = render 'projects/blob/header_content', blob: blob - .file-actions.hidden-xs + .file-actions = render 'projects/blob/viewer_switcher', blob: blob unless blame .btn-group{ role: "group" }< diff --git a/app/views/projects/branches/index.html.haml b/app/views/projects/branches/index.html.haml index aade310236e..fb770764364 100644 --- a/app/views/projects/branches/index.html.haml +++ b/app/views/projects/branches/index.html.haml @@ -38,7 +38,7 @@ - if @branches.any? %ul.content-list.all-branches - @branches.each do |branch| - = render "projects/branches/branch", branch: branch, merged: @repository.merged_to_root_ref?(branch, @merged_branch_names) + = render "projects/branches/branch", branch: branch, merged: @merged_branch_names.include?(branch.name) = paginate @branches, theme: 'gitlab' - else .nothing-here-block diff --git a/app/views/projects/buttons/_star.html.haml b/app/views/projects/buttons/_star.html.haml index c82ae35a685..0a54c736761 100644 --- a/app/views/projects/buttons/_star.html.haml +++ b/app/views/projects/buttons/_star.html.haml @@ -1,10 +1,10 @@ - if current_user = link_to toggle_star_project_path(@project), { class: 'btn star-btn toggle-star', method: :post, remote: true } do - if current_user.starred?(@project) - = icon('star') + = sprite_icon('star') %span.starred= _('Unstar') - else - = icon('star-o') + = sprite_icon('star-o') %span= s_('StarProject|Star') .count-with-arrow %span.arrow @@ -13,7 +13,7 @@ - else = link_to new_user_session_path, class: 'btn has-tooltip star-btn', title: _('You must sign in to star a project') do - = icon('star') + = sprite_icon('star') #{ s_('StarProject|Star') } .count-with-arrow %span.arrow diff --git a/app/views/projects/environments/folder.html.haml b/app/views/projects/environments/folder.html.haml index 1bcc955ddc8..d9c9f0ed546 100644 --- a/app/views/projects/environments/folder.html.haml +++ b/app/views/projects/environments/folder.html.haml @@ -5,6 +5,8 @@ = page_specific_javascript_bundle_tag('common_vue') = page_specific_javascript_bundle_tag("environments_folder") -#environments-folder-list-view{ data: { "can-create-deployment" => can?(current_user, :create_deployment, @project).to_s, +#environments-folder-list-view{ data: { endpoint: folder_project_environments_path(@project, @folder, format: :json), + "folder-name" => @folder, + "can-create-deployment" => can?(current_user, :create_deployment, @project).to_s, "can-read-environment" => can?(current_user, :read_environment, @project).to_s, "css-class" => container_class } } diff --git a/app/views/projects/environments/index.html.haml b/app/views/projects/environments/index.html.haml index 2e85f608823..88f1348da47 100644 --- a/app/views/projects/environments/index.html.haml +++ b/app/views/projects/environments/index.html.haml @@ -3,15 +3,13 @@ - add_to_breadcrumbs("Pipelines", project_pipelines_path(@project)) - content_for :page_specific_javascripts do - = page_specific_javascript_bundle_tag('common_vue') + = page_specific_javascript_bundle_tag("common_vue") = page_specific_javascript_bundle_tag("environments") #environments-list-view{ data: { environments_data: environments_list_data, "can-create-deployment" => can?(current_user, :create_deployment, @project).to_s, "can-read-environment" => can?(current_user, :read_environment, @project).to_s, "can-create-environment" => can?(current_user, :create_environment, @project).to_s, - "project-environments-path" => project_environments_path(@project), - "project-stopped-environments-path" => project_environments_path(@project, scope: :stopped), "new-environment-path" => new_project_environment_path(@project), "help-page-path" => help_page_path("ci/environments"), "css-class" => container_class } } diff --git a/app/views/shared/groups/_group.html.haml b/app/views/shared/groups/_group.html.haml index 059dd24be6d..321d8767d08 100644 --- a/app/views/shared/groups/_group.html.haml +++ b/app/views/shared/groups/_group.html.haml @@ -9,7 +9,7 @@ .controls.hidden-xs - if can?(current_user, :admin_group, group) = link_to edit_group_path(group), class: "btn" do - = icon('cogs') + = sprite_icon('settings') = link_to leave_group_group_members_path(group), data: { confirm: leave_confirmation_message(group) }, method: :delete, class: "btn", title: s_("GroupsTree|Leave this group") do = icon('sign-out') diff --git a/app/workers/pipeline_schedule_worker.rb b/app/workers/pipeline_schedule_worker.rb index d7087f20dfc..7320db1065e 100644 --- a/app/workers/pipeline_schedule_worker.rb +++ b/app/workers/pipeline_schedule_worker.rb @@ -9,7 +9,7 @@ class PipelineScheduleWorker pipeline = Ci::CreatePipelineService.new(schedule.project, schedule.owner, ref: schedule.ref) - .execute(:schedule, save_on_errors: false, schedule: schedule) + .execute(:schedule, ignore_skip_ci: true, save_on_errors: false, schedule: schedule) schedule.deactivate! unless pipeline.persisted? rescue => e diff --git a/changelogs/unreleased/28377-add-edit-button-to-mobile-file-view.yml b/changelogs/unreleased/28377-add-edit-button-to-mobile-file-view.yml new file mode 100644 index 00000000000..b6646379b8d --- /dev/null +++ b/changelogs/unreleased/28377-add-edit-button-to-mobile-file-view.yml @@ -0,0 +1,5 @@ +--- +title: Add edit button to mobile file view +merge_request: 15199 +author: Travis Miller +type: added diff --git a/changelogs/unreleased/feature-disable-password-authentication.yml b/changelogs/unreleased/feature-disable-password-authentication.yml new file mode 100644 index 00000000000..999203f12ce --- /dev/null +++ b/changelogs/unreleased/feature-disable-password-authentication.yml @@ -0,0 +1,5 @@ +--- +title: Allow password authentication to be disabled entirely +merge_request: 15223 +author: Markus Koller +type: changed diff --git a/changelogs/unreleased/fix-sm-37991-avoid-deactivation-when-pipeline-schedules-execute-a-commit-includes-ci-skip.yml b/changelogs/unreleased/fix-sm-37991-avoid-deactivation-when-pipeline-schedules-execute-a-commit-includes-ci-skip.yml new file mode 100644 index 00000000000..4e525c875ca --- /dev/null +++ b/changelogs/unreleased/fix-sm-37991-avoid-deactivation-when-pipeline-schedules-execute-a-commit-includes-ci-skip.yml @@ -0,0 +1,6 @@ +--- +title: Avoid deactivation when pipeline schedules execute a branch includes `[ci skip]` + comment +merge_request: 15405 +author: +type: fixed diff --git a/changelogs/unreleased/jk-group-mentions-fix.yml b/changelogs/unreleased/jk-group-mentions-fix.yml new file mode 100644 index 00000000000..a28e3a87b6d --- /dev/null +++ b/changelogs/unreleased/jk-group-mentions-fix.yml @@ -0,0 +1,5 @@ +--- +title: Fix link text from group context +merge_request: +author: +type: fixed diff --git a/changelogs/unreleased/use-merge-requests-diff-id-column.yml b/changelogs/unreleased/use-merge-requests-diff-id-column.yml new file mode 100644 index 00000000000..da4106ec8cf --- /dev/null +++ b/changelogs/unreleased/use-merge-requests-diff-id-column.yml @@ -0,0 +1,5 @@ +--- +title: Make finding most recent merge request diffs more efficient +merge_request: +author: +type: performance diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb index f7c83f7b0f7..f10f0cdf42c 100644 --- a/config/initializers/1_settings.rb +++ b/config/initializers/1_settings.rb @@ -256,7 +256,7 @@ rescue ArgumentError # no user configured end Settings.gitlab['time_zone'] ||= nil Settings.gitlab['signup_enabled'] ||= true if Settings.gitlab['signup_enabled'].nil? -Settings.gitlab['password_authentication_enabled'] ||= true if Settings.gitlab['password_authentication_enabled'].nil? +Settings.gitlab['signin_enabled'] ||= true if Settings.gitlab['signin_enabled'].nil? Settings.gitlab['restricted_visibility_levels'] = Settings.__send__(:verify_constant_array, Gitlab::VisibilityLevel, Settings.gitlab['restricted_visibility_levels'], []) Settings.gitlab['username_changing_enabled'] = true if Settings.gitlab['username_changing_enabled'].nil? Settings.gitlab['issue_closing_pattern'] = '((?:[Cc]los(?:e[sd]?|ing)|[Ff]ix(?:e[sd]|ing)?|[Rr]esolv(?:e[sd]?|ing)|[Ii]mplement(?:s|ed|ing)?)(:?) +(?:(?:issues? +)?%{issue_ref}(?:(?:, *| +and +)?)|([A-Z][A-Z0-9_]+-\d+))+)' if Settings.gitlab['issue_closing_pattern'].nil? diff --git a/config/routes.rb b/config/routes.rb index fc13dc4865f..4f27fea0e92 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -100,7 +100,5 @@ Rails.application.routes.draw do root to: "root#index" - draw :test if Rails.env.test? - get '*unmatched_route', to: 'application#route_not_found' end diff --git a/config/routes/test.rb b/config/routes/test.rb deleted file mode 100644 index ac477cdbbbc..00000000000 --- a/config/routes/test.rb +++ /dev/null @@ -1,2 +0,0 @@ -get '/unicorn_test/pid' => 'unicorn_test#pid' -post '/unicorn_test/kill' => 'unicorn_test#kill' diff --git a/db/migrate/20171106133143_rename_application_settings_password_authentication_enabled_to_password_authentication_enabled_for_web.rb b/db/migrate/20171106133143_rename_application_settings_password_authentication_enabled_to_password_authentication_enabled_for_web.rb new file mode 100644 index 00000000000..6d369e93361 --- /dev/null +++ b/db/migrate/20171106133143_rename_application_settings_password_authentication_enabled_to_password_authentication_enabled_for_web.rb @@ -0,0 +1,15 @@ +class RenameApplicationSettingsPasswordAuthenticationEnabledToPasswordAuthenticationEnabledForWeb < ActiveRecord::Migration + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + + disable_ddl_transaction! + + def up + rename_column_concurrently :application_settings, :password_authentication_enabled, :password_authentication_enabled_for_web + end + + def down + cleanup_concurrent_column_rename :application_settings, :password_authentication_enabled_for_web, :password_authentication_enabled + end +end diff --git a/db/migrate/20171106133911_add_password_authentication_enabled_for_git_to_application_settings.rb b/db/migrate/20171106133911_add_password_authentication_enabled_for_git_to_application_settings.rb new file mode 100644 index 00000000000..b8aa600864e --- /dev/null +++ b/db/migrate/20171106133911_add_password_authentication_enabled_for_git_to_application_settings.rb @@ -0,0 +1,9 @@ +class AddPasswordAuthenticationEnabledForGitToApplicationSettings < ActiveRecord::Migration + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + + def change + add_column :application_settings, :password_authentication_enabled_for_git, :boolean, default: true, null: false + end +end diff --git a/db/migrate/20171115164540_populate_merge_requests_latest_merge_request_diff_id_take_two.rb b/db/migrate/20171115164540_populate_merge_requests_latest_merge_request_diff_id_take_two.rb new file mode 100644 index 00000000000..27b6b4ebddc --- /dev/null +++ b/db/migrate/20171115164540_populate_merge_requests_latest_merge_request_diff_id_take_two.rb @@ -0,0 +1,30 @@ +# This is identical to the stolen background migration, which already has specs. +class PopulateMergeRequestsLatestMergeRequestDiffIdTakeTwo < ActiveRecord::Migration + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + BATCH_SIZE = 1_000 + + class MergeRequest < ActiveRecord::Base + self.table_name = 'merge_requests' + + include ::EachBatch + end + + disable_ddl_transaction! + + def up + Gitlab::BackgroundMigration.steal('PopulateMergeRequestsLatestMergeRequestDiffId') + + update = ' + latest_merge_request_diff_id = ( + SELECT MAX(id) + FROM merge_request_diffs + WHERE merge_requests.id = merge_request_diffs.merge_request_id + )'.squish + + MergeRequest.where(latest_merge_request_diff_id: nil).each_batch(of: BATCH_SIZE) do |relation| + relation.update_all(update) + end + end +end diff --git a/db/migrate/20171116135628_add_environment_scope_to_clusters.rb b/db/migrate/20171116135628_add_environment_scope_to_clusters.rb new file mode 100644 index 00000000000..cce757095dd --- /dev/null +++ b/db/migrate/20171116135628_add_environment_scope_to_clusters.rb @@ -0,0 +1,15 @@ +class AddEnvironmentScopeToClusters < ActiveRecord::Migration + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + + disable_ddl_transaction! + + def up + add_column_with_default(:clusters, :environment_scope, :string, default: '*') + end + + def down + remove_column(:clusters, :environment_scope) + end +end diff --git a/db/post_migrate/20171013104327_migrate_gcp_clusters_to_new_clusters_architectures.rb b/db/post_migrate/20171013104327_migrate_gcp_clusters_to_new_clusters_architectures.rb index 4758c694563..28cd0f70cc2 100644 --- a/db/post_migrate/20171013104327_migrate_gcp_clusters_to_new_clusters_architectures.rb +++ b/db/post_migrate/20171013104327_migrate_gcp_clusters_to_new_clusters_architectures.rb @@ -74,7 +74,6 @@ class MigrateGcpClustersToNewClustersArchitectures < ActiveRecord::Migration encrypted_access_token_iv: gcp_cluster.encrypted_gcp_token_iv }, platform_kubernetes_attributes: { - cluster_id: gcp_cluster.id, api_url: api_url(gcp_cluster.endpoint), ca_cert: gcp_cluster.ca_cert, namespace: gcp_cluster.project_namespace, diff --git a/db/post_migrate/20171106133144_cleanup_application_settings_password_authentication_enabled_rename.rb b/db/post_migrate/20171106133144_cleanup_application_settings_password_authentication_enabled_rename.rb new file mode 100644 index 00000000000..d54ff3d5f5e --- /dev/null +++ b/db/post_migrate/20171106133144_cleanup_application_settings_password_authentication_enabled_rename.rb @@ -0,0 +1,15 @@ +class CleanupApplicationSettingsPasswordAuthenticationEnabledRename < ActiveRecord::Migration + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + + disable_ddl_transaction! + + def up + cleanup_concurrent_column_rename :application_settings, :password_authentication_enabled, :password_authentication_enabled_for_web + end + + def down + rename_column_concurrently :application_settings, :password_authentication_enabled_for_web, :password_authentication_enabled + end +end diff --git a/db/schema.rb b/db/schema.rb index a82270390f1..d10561099b7 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -129,7 +129,6 @@ ActiveRecord::Schema.define(version: 20171121144800) do t.boolean "prometheus_metrics_enabled", default: false, null: false t.boolean "help_page_hide_commercial_content", default: false t.string "help_page_support_url" - t.boolean "password_authentication_enabled" t.integer "performance_bar_allowed_group_id" t.boolean "hashed_storage_enabled", default: false, null: false t.boolean "project_export_enabled", default: true, null: false @@ -149,6 +148,8 @@ ActiveRecord::Schema.define(version: 20171121144800) do t.boolean "throttle_authenticated_web_enabled", default: false, null: false t.integer "throttle_authenticated_web_requests_per_period", default: 7200, null: false t.integer "throttle_authenticated_web_period_in_seconds", default: 3600, null: false + t.boolean "password_authentication_enabled_for_web" + t.boolean "password_authentication_enabled_for_git", default: true end create_table "audit_events", force: :cascade do |t| @@ -523,6 +524,7 @@ ActiveRecord::Schema.define(version: 20171121144800) do t.datetime_with_timezone "updated_at", null: false t.boolean "enabled", default: true t.string "name", null: false + t.string "environment_scope", default: "*", null: false end add_index "clusters", ["enabled"], name: "index_clusters_on_enabled", using: :btree diff --git a/doc/administration/auth/ldap.md b/doc/administration/auth/ldap.md index ad903aef896..6b5a0f139c5 100644 --- a/doc/administration/auth/ldap.md +++ b/doc/administration/auth/ldap.md @@ -30,6 +30,12 @@ immediately block all access. >**Note**: GitLab EE supports a configurable sync time, with a default of one hour. +## Git password authentication + +LDAP-enabled users can always authenticate with Git using their GitLab username +or email and LDAP password, even if password authentication for Git is disabled +in the application settings. + ## Configuration To enable LDAP integration you need to add your LDAP server settings in diff --git a/doc/administration/repository_storages.md b/doc/administration/repository_storages.md index 9d41ba77f34..cf6de15743f 100644 --- a/doc/administration/repository_storages.md +++ b/doc/administration/repository_storages.md @@ -1,3 +1 @@ -# Repository storages - -This document was moved to a [new location](repository_storage_paths.md). +This document was moved to [another location](repository_storage_paths.md). diff --git a/doc/api/settings.md b/doc/api/settings.md index b27220f57f4..22fb2baa8ec 100644 --- a/doc/api/settings.md +++ b/doc/api/settings.md @@ -25,7 +25,7 @@ Example response: "id" : 1, "default_branch_protection" : 2, "restricted_visibility_levels" : [], - "password_authentication_enabled" : true, + "password_authentication_enabled_for_web" : true, "after_sign_out_path" : null, "max_attachment_size" : 10, "user_oauth_applications" : true, @@ -117,7 +117,8 @@ PUT /application/settings | `metrics_port` | integer | no | The UDP port to use for connecting to InfluxDB | | `metrics_sample_interval` | integer | yes (if `metrics_enabled` is `true`) | The sampling interval in seconds. | | `metrics_timeout` | integer | yes (if `metrics_enabled` is `true`) | The amount of seconds after which InfluxDB will time out. | -| `password_authentication_enabled` | boolean | no | Enable authentication via a GitLab account password. Default is `true`. | +| `password_authentication_enabled_for_web` | boolean | no | Enable authentication for the web interface via a GitLab account password. Default is `true`. | +| `password_authentication_enabled_for_git` | boolean | no | Enable authentication for Git over HTTP(S) via a GitLab account password. Default is `true`. | | `performance_bar_allowed_group_id` | string | no | The group that is allowed to enable the performance bar | | `performance_bar_enabled` | boolean | no | Allow enabling the performance bar | | `plantuml_enabled` | boolean | no | Enable PlantUML integration. Default is `false`. | @@ -165,7 +166,7 @@ Example response: "id": 1, "default_projects_limit": 100000, "signup_enabled": true, - "password_authentication_enabled": true, + "password_authentication_enabled_for_web": true, "gravatar_enabled": true, "sign_in_text": "", "created_at": "2015-06-12T15:51:55.432Z", diff --git a/doc/development/doc_styleguide.md b/doc/development/doc_styleguide.md index 0e4ffbd7910..aaa7032cadb 100644 --- a/doc/development/doc_styleguide.md +++ b/doc/development/doc_styleguide.md @@ -303,10 +303,10 @@ GitLab.com or http://docs.gitlab.com. Make sure this is discussed with the Documentation team beforehand. If you indeed need to change a document's location, do NOT remove the old -document, but rather put a text in it that points to the new location, like: +document, but rather replace all of its contents with a new line: ``` -This document was moved to [path/to/new_doc.md](path/to/new_doc.md). +This document was moved to [another location](path/to/new_doc.md). ``` where `path/to/new_doc.md` is the relative path to the root directory `doc/`. @@ -320,7 +320,7 @@ For example, if you were to move `doc/workflow/lfs/lfs_administration.md` to 1. Replace the contents of `doc/workflow/lfs/lfs_administration.md` with: ``` - This document was moved to [administration/lfs.md](../../administration/lfs.md). + This document was moved to [another location](../../administration/lfs.md). ``` 1. Find and replace any occurrences of the old location with the new one. diff --git a/doc/user/project/issues/automatic_issue_closing.md b/doc/user/project/issues/automatic_issue_closing.md index 402a2a3c727..b9607243c8a 100644 --- a/doc/user/project/issues/automatic_issue_closing.md +++ b/doc/user/project/issues/automatic_issue_closing.md @@ -12,8 +12,9 @@ in the project's default branch. If a commit message or merge request description contains a sentence matching a certain regular expression, all issues referenced from the matched text will -be closed. This happens when the commit is pushed to a project's **default** -branch, or when a commit or merge request is merged into it. +be closed. This happens when the commit is pushed to a project's +[**default** branch](../repository/branches/index.md#default-branch), or when a +commit or merge request is merged into it. ## Default closing pattern value diff --git a/doc/workflow/importing/README.md b/doc/workflow/importing/README.md index f753708ad89..e0a445920b4 100644 --- a/doc/workflow/importing/README.md +++ b/doc/workflow/importing/README.md @@ -1 +1 @@ -This document was moved to a [new location](../../user/project/import/index.md).
+This document was moved to [another location](../../user/project/import/index.md).
diff --git a/doc/workflow/importing/import_projects_from_bitbucket.md b/doc/workflow/importing/import_projects_from_bitbucket.md index 248c3990372..ec9a11f390e 100644 --- a/doc/workflow/importing/import_projects_from_bitbucket.md +++ b/doc/workflow/importing/import_projects_from_bitbucket.md @@ -1 +1 @@ -This document was moved to a [new location](../../user/project/import/bitbucket.md).
+This document was moved to [another location](../../user/project/import/bitbucket.md).
diff --git a/doc/workflow/importing/import_projects_from_fogbugz.md b/doc/workflow/importing/import_projects_from_fogbugz.md index 050746e2b4d..876eb0434f0 100644 --- a/doc/workflow/importing/import_projects_from_fogbugz.md +++ b/doc/workflow/importing/import_projects_from_fogbugz.md @@ -1 +1 @@ -This document was moved to a [new location](../../user/project/import/fogbugz.md). +This document was moved to [another location](../../user/project/import/fogbugz.md). diff --git a/doc/workflow/importing/import_projects_from_gitea.md b/doc/workflow/importing/import_projects_from_gitea.md index cb90c490b0f..8b55b6c23eb 100644 --- a/doc/workflow/importing/import_projects_from_gitea.md +++ b/doc/workflow/importing/import_projects_from_gitea.md @@ -1 +1 @@ -This document was moved to a [new location](../../user/project/import/gitea.md). +This document was moved to [another location](../../user/project/import/gitea.md). diff --git a/doc/workflow/importing/import_projects_from_github.md b/doc/workflow/importing/import_projects_from_github.md index 13639feaa04..72dfe5403c3 100644 --- a/doc/workflow/importing/import_projects_from_github.md +++ b/doc/workflow/importing/import_projects_from_github.md @@ -1 +1 @@ -This document was moved to a [new location](../../user/project/import/github.md).
+This document was moved to [another location](../../user/project/import/github.md).
diff --git a/doc/workflow/importing/import_projects_from_gitlab_com.md b/doc/workflow/importing/import_projects_from_gitlab_com.md index df4c180919a..3256088c014 100644 --- a/doc/workflow/importing/import_projects_from_gitlab_com.md +++ b/doc/workflow/importing/import_projects_from_gitlab_com.md @@ -1 +1 @@ -This document was moved to a [new location](../../user/project/import/gitlab_com.md). +This document was moved to [another location](../../user/project/import/gitlab_com.md). diff --git a/doc/workflow/importing/migrating_from_svn.md b/doc/workflow/importing/migrating_from_svn.md index 81df3fbcdbb..32a75a6c6af 100644 --- a/doc/workflow/importing/migrating_from_svn.md +++ b/doc/workflow/importing/migrating_from_svn.md @@ -1 +1 @@ -This document was moved to a [new location](../../user/project/import/svn.md). +This document was moved to [another location](../../user/project/import/svn.md). diff --git a/lib/api/branches.rb b/lib/api/branches.rb index cdef1b546a9..0791a110c39 100644 --- a/lib/api/branches.rb +++ b/lib/api/branches.rb @@ -81,9 +81,9 @@ module API service_args = [user_project, current_user, protected_branch_params] protected_branch = if protected_branch - ::ProtectedBranches::ApiUpdateService.new(*service_args).execute(protected_branch) + ::ProtectedBranches::LegacyApiUpdateService.new(*service_args).execute(protected_branch) else - ::ProtectedBranches::ApiCreateService.new(*service_args).execute + ::ProtectedBranches::LegacyApiCreateService.new(*service_args).execute end if protected_branch.valid? diff --git a/lib/api/entities.rb b/lib/api/entities.rb index 16ae99b5c6c..7d5d68c8f14 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -242,7 +242,11 @@ module API end expose :merged do |repo_branch, options| - options[:project].repository.merged_to_root_ref?(repo_branch, options[:merged_branch_names]) + if options[:merged_branch_names] + options[:merged_branch_names].include?(repo_branch.name) + else + options[:project].repository.merged_to_root_ref?(repo_branch) + end end expose :protected do |repo_branch, options| @@ -763,7 +767,10 @@ module API expose(:default_project_visibility) { |setting, _options| Gitlab::VisibilityLevel.string_level(setting.default_project_visibility) } expose(:default_snippet_visibility) { |setting, _options| Gitlab::VisibilityLevel.string_level(setting.default_snippet_visibility) } expose(:default_group_visibility) { |setting, _options| Gitlab::VisibilityLevel.string_level(setting.default_group_visibility) } - expose :password_authentication_enabled, as: :signin_enabled + + # support legacy names, can be removed in v5 + expose :password_authentication_enabled_for_web, as: :password_authentication_enabled + expose :password_authentication_enabled_for_web, as: :signin_enabled end class Release < Grape::Entity diff --git a/lib/api/merge_requests.rb b/lib/api/merge_requests.rb index 726f09e3669..5b4642a2f57 100644 --- a/lib/api/merge_requests.rb +++ b/lib/api/merge_requests.rb @@ -21,7 +21,7 @@ module API return merge_requests if args[:view] == 'simple' merge_requests - .preload(:notes, :author, :assignee, :milestone, :merge_request_diff, :labels, :timelogs) + .preload(:notes, :author, :assignee, :milestone, :latest_merge_request_diff, :labels, :timelogs) end params :merge_requests_params do diff --git a/lib/api/settings.rb b/lib/api/settings.rb index 851b226e9e5..06373fe5069 100644 --- a/lib/api/settings.rb +++ b/lib/api/settings.rb @@ -44,9 +44,11 @@ module API requires :domain_blacklist, type: String, desc: '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' end optional :after_sign_up_text, type: String, desc: 'Text shown after sign up' - optional :password_authentication_enabled, type: Boolean, desc: 'Flag indicating if password authentication is enabled' - optional :signin_enabled, type: Boolean, desc: 'Flag indicating if password authentication is enabled' - mutually_exclusive :password_authentication_enabled, :signin_enabled + optional :password_authentication_enabled_for_web, type: Boolean, desc: 'Flag indicating if password authentication is enabled for the web interface' + optional :password_authentication_enabled, type: Boolean, desc: 'Flag indicating if password authentication is enabled for the web interface' # support legacy names, can be removed in v5 + optional :signin_enabled, type: Boolean, desc: 'Flag indicating if password authentication is enabled for the web interface' # support legacy names, can be removed in v5 + mutually_exclusive :password_authentication_enabled_for_web, :password_authentication_enabled, :signin_enabled + optional :password_authentication_enabled_for_git, type: Boolean, desc: 'Flag indicating if password authentication is enabled for Git over HTTP(S)' optional :require_two_factor_authentication, type: Boolean, desc: 'Require all users to setup Two-factor authentication' given require_two_factor_authentication: ->(val) { val } do requires :two_factor_grace_period, type: Integer, desc: 'Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication' @@ -135,8 +137,11 @@ module API put "application/settings" do attrs = declared_params(include_missing: false) + # support legacy names, can be removed in v5 if attrs.has_key?(:signin_enabled) - attrs[:password_authentication_enabled] = attrs.delete(:signin_enabled) + attrs[:password_authentication_enabled_for_web] = attrs.delete(:signin_enabled) + elsif attrs.has_key?(:password_authentication_enabled) + attrs[:password_authentication_enabled_for_web] = attrs.delete(:password_authentication_enabled) end if current_settings.update_attributes(attrs) diff --git a/lib/api/v3/entities.rb b/lib/api/v3/entities.rb index afdd7b83998..c17b6f45ed8 100644 --- a/lib/api/v3/entities.rb +++ b/lib/api/v3/entities.rb @@ -172,8 +172,8 @@ module API expose :id expose :default_projects_limit expose :signup_enabled - expose :password_authentication_enabled - expose :password_authentication_enabled, as: :signin_enabled + expose :password_authentication_enabled_for_web, as: :password_authentication_enabled + expose :password_authentication_enabled_for_web, as: :signin_enabled expose :gravatar_enabled expose :sign_in_text expose :after_sign_up_text diff --git a/lib/api/v3/settings.rb b/lib/api/v3/settings.rb index 202011cfcbe..9b4ab7630fb 100644 --- a/lib/api/v3/settings.rb +++ b/lib/api/v3/settings.rb @@ -44,8 +44,8 @@ module API requires :domain_blacklist, type: String, desc: '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' end optional :after_sign_up_text, type: String, desc: 'Text shown after sign up' - optional :password_authentication_enabled, type: Boolean, desc: 'Flag indicating if password authentication is enabled' - optional :signin_enabled, type: Boolean, desc: 'Flag indicating if password authentication is enabled' + optional :password_authentication_enabled, type: Boolean, desc: 'Flag indicating if password authentication is enabled for the web interface' + optional :signin_enabled, type: Boolean, desc: 'Flag indicating if password authentication is enabled for the web interface' mutually_exclusive :password_authentication_enabled, :signin_enabled optional :require_two_factor_authentication, type: Boolean, desc: 'Require all users to setup Two-factor authentication' given require_two_factor_authentication: ->(val) { val } do @@ -131,7 +131,9 @@ module API attrs = declared_params(include_missing: false) if attrs.has_key?(:signin_enabled) - attrs[:password_authentication_enabled] = attrs.delete(:signin_enabled) + attrs[:password_authentication_enabled_for_web] = attrs.delete(:signin_enabled) + elsif attrs.has_key?(:password_authentication_enabled) + attrs[:password_authentication_enabled_for_web] = attrs.delete(:password_authentication_enabled) end if current_settings.update_attributes(attrs) diff --git a/lib/banzai/filter/abstract_reference_filter.rb b/lib/banzai/filter/abstract_reference_filter.rb index 9fef386de16..8975395aff1 100644 --- a/lib/banzai/filter/abstract_reference_filter.rb +++ b/lib/banzai/filter/abstract_reference_filter.rb @@ -213,7 +213,8 @@ module Banzai end def object_link_text(object, matches) - text = object.reference_link_text(context[:project]) + parent = context[:project] || context[:group] + text = object.reference_link_text(parent) extras = object_link_text_extras(object, matches) text += " (#{extras.join(", ")})" if extras.any? diff --git a/lib/gitlab/auth.rb b/lib/gitlab/auth.rb index cbbc51db99e..9670207a105 100644 --- a/lib/gitlab/auth.rb +++ b/lib/gitlab/auth.rb @@ -34,7 +34,7 @@ module Gitlab rate_limit!(ip, success: result.success?, login: login) Gitlab::Auth::UniqueIpsLimiter.limit_user!(result.actor) - return result if result.success? || current_application_settings.password_authentication_enabled? || Gitlab::LDAP::Config.enabled? + return result if result.success? || authenticate_using_internal_or_ldap_password? # If sign-in is disabled and LDAP is not configured, recommend a # personal access token on failed auth attempts @@ -45,6 +45,10 @@ module Gitlab # Avoid resource intensive login checks if password is not provided return unless password.present? + # Nothing to do here if internal auth is disabled and LDAP is + # not configured + return unless authenticate_using_internal_or_ldap_password? + Gitlab::Auth::UniqueIpsLimiter.limit_user! do user = User.by_login(login) @@ -52,10 +56,8 @@ module Gitlab # LDAP users are only authenticated via LDAP if user.nil? || user.ldap_user? # Second chance - try LDAP authentication - return unless Gitlab::LDAP::Config.enabled? - Gitlab::LDAP::Authentication.login(login, password) - else + elsif current_application_settings.password_authentication_enabled_for_git? user if user.active? && user.valid_password?(password) end end @@ -84,6 +86,10 @@ module Gitlab private + def authenticate_using_internal_or_ldap_password? + current_application_settings.password_authentication_enabled_for_git? || Gitlab::LDAP::Config.enabled? + end + def service_request_check(login, password, project) matched_login = /(?<service>^[a-zA-Z]*-ci)-token$/.match(login) diff --git a/lib/gitlab/background_migration/.rubocop.yml b/lib/gitlab/background_migration/.rubocop.yml new file mode 100644 index 00000000000..8242821cedc --- /dev/null +++ b/lib/gitlab/background_migration/.rubocop.yml @@ -0,0 +1,52 @@ +# For background migrations we define a custom set of rules to make it less +# difficult to review these migrations. To reduce the complexity of these +# migrations some rules may be stricter than the defaults set in the root +# .rubocop.yml file. +--- +inherit_from: ../../../.rubocop.yml + +Metrics/AbcSize: + Enabled: true + Max: 30 + Details: > + Code that involves a lot of branches can be very hard to wrap your head + around. + +Metrics/PerceivedComplexity: + Enabled: true + +Metrics/LineLength: + Enabled: true + Details: > + Long lines are very hard to read and make it more difficult to review + changes. + +Metrics/MethodLength: + Enabled: true + Max: 30 + Details: > + Long methods can be very hard to review. Consider splitting this method up + into separate methods. + +Metrics/ClassLength: + Enabled: true + Details: > + Long classes can be very hard to review. Consider splitting this class up + into multiple classes. + +Metrics/BlockLength: + Enabled: true + Details: > + Long blocks can be hard to read. Consider splitting the code into separate + methods. + +Style/Documentation: + Enabled: true + Details: > + Adding documentation makes it easier to figure out what a migration is + supposed to do. + +Style/FrozenStringLiteralComment: + Enabled: true + Details: >- + This removes the need for calling "freeze", reducing noise in the code. diff --git a/lib/gitlab/background_migration/create_fork_network_memberships_range.rb b/lib/gitlab/background_migration/create_fork_network_memberships_range.rb index 67a39d28944..03b17b319fa 100644 --- a/lib/gitlab/background_migration/create_fork_network_memberships_range.rb +++ b/lib/gitlab/background_migration/create_fork_network_memberships_range.rb @@ -1,3 +1,7 @@ +# frozen_string_literal: true +# rubocop:disable Metrics/LineLength +# rubocop:disable Style/Documentation + module Gitlab module BackgroundMigration class CreateForkNetworkMembershipsRange diff --git a/lib/gitlab/background_migration/create_gpg_key_subkeys_from_gpg_keys.rb b/lib/gitlab/background_migration/create_gpg_key_subkeys_from_gpg_keys.rb index e94719db72e..c2bf42f846d 100644 --- a/lib/gitlab/background_migration/create_gpg_key_subkeys_from_gpg_keys.rb +++ b/lib/gitlab/background_migration/create_gpg_key_subkeys_from_gpg_keys.rb @@ -1,3 +1,7 @@ +# frozen_string_literal: true +# rubocop:disable Metrics/LineLength +# rubocop:disable Style/Documentation + class Gitlab::BackgroundMigration::CreateGpgKeySubkeysFromGpgKeys class GpgKey < ActiveRecord::Base self.table_name = 'gpg_keys' diff --git a/lib/gitlab/background_migration/delete_conflicting_redirect_routes_range.rb b/lib/gitlab/background_migration/delete_conflicting_redirect_routes_range.rb index b1411be3016..a1af045a71f 100644 --- a/lib/gitlab/background_migration/delete_conflicting_redirect_routes_range.rb +++ b/lib/gitlab/background_migration/delete_conflicting_redirect_routes_range.rb @@ -1,3 +1,7 @@ +# frozen_string_literal: true +# rubocop:disable Metrics/LineLength +# rubocop:disable Style/Documentation + module Gitlab module BackgroundMigration class DeleteConflictingRedirectRoutesRange diff --git a/lib/gitlab/background_migration/deserialize_merge_request_diffs_and_commits.rb b/lib/gitlab/background_migration/deserialize_merge_request_diffs_and_commits.rb index 380802258f5..fd5cbf76e47 100644 --- a/lib/gitlab/background_migration/deserialize_merge_request_diffs_and_commits.rb +++ b/lib/gitlab/background_migration/deserialize_merge_request_diffs_and_commits.rb @@ -1,3 +1,9 @@ +# frozen_string_literal: true +# rubocop:disable Metrics/MethodLength +# rubocop:disable Metrics/LineLength +# rubocop:disable Metrics/AbcSize +# rubocop:disable Style/Documentation + module Gitlab module BackgroundMigration class DeserializeMergeRequestDiffsAndCommits diff --git a/lib/gitlab/background_migration/migrate_build_stage_id_reference.rb b/lib/gitlab/background_migration/migrate_build_stage_id_reference.rb index 91540127ea9..0a8a4313cd5 100644 --- a/lib/gitlab/background_migration/migrate_build_stage_id_reference.rb +++ b/lib/gitlab/background_migration/migrate_build_stage_id_reference.rb @@ -1,3 +1,6 @@ +# frozen_string_literal: true +# rubocop:disable Style/Documentation + module Gitlab module BackgroundMigration class MigrateBuildStageIdReference diff --git a/lib/gitlab/background_migration/migrate_events_to_push_event_payloads.rb b/lib/gitlab/background_migration/migrate_events_to_push_event_payloads.rb index 432f7c3e706..84ac00f1a5c 100644 --- a/lib/gitlab/background_migration/migrate_events_to_push_event_payloads.rb +++ b/lib/gitlab/background_migration/migrate_events_to_push_event_payloads.rb @@ -1,3 +1,7 @@ +# frozen_string_literal: true +# rubocop:disable Metrics/LineLength +# rubocop:disable Style/Documentation + module Gitlab module BackgroundMigration # Class that migrates events for the new push event payloads setup. All diff --git a/lib/gitlab/background_migration/migrate_stage_status.rb b/lib/gitlab/background_migration/migrate_stage_status.rb index b1ff0900709..0e5c7f092f2 100644 --- a/lib/gitlab/background_migration/migrate_stage_status.rb +++ b/lib/gitlab/background_migration/migrate_stage_status.rb @@ -1,3 +1,7 @@ +# frozen_string_literal: true +# rubocop:disable Metrics/AbcSize +# rubocop:disable Style/Documentation + module Gitlab module BackgroundMigration class MigrateStageStatus diff --git a/lib/gitlab/background_migration/migrate_system_uploads_to_new_folder.rb b/lib/gitlab/background_migration/migrate_system_uploads_to_new_folder.rb index 0881244ed49..7f243073fd0 100644 --- a/lib/gitlab/background_migration/migrate_system_uploads_to_new_folder.rb +++ b/lib/gitlab/background_migration/migrate_system_uploads_to_new_folder.rb @@ -1,3 +1,7 @@ +# frozen_string_literal: true +# rubocop:disable Metrics/LineLength +# rubocop:disable Style/Documentation + module Gitlab module BackgroundMigration class MigrateSystemUploadsToNewFolder diff --git a/lib/gitlab/background_migration/move_personal_snippet_files.rb b/lib/gitlab/background_migration/move_personal_snippet_files.rb index 07cec96bcc3..a4ef51fd0e8 100644 --- a/lib/gitlab/background_migration/move_personal_snippet_files.rb +++ b/lib/gitlab/background_migration/move_personal_snippet_files.rb @@ -1,3 +1,7 @@ +# frozen_string_literal: true +# rubocop:disable Metrics/LineLength +# rubocop:disable Style/Documentation + module Gitlab module BackgroundMigration class MovePersonalSnippetFiles diff --git a/lib/gitlab/background_migration/normalize_ldap_extern_uids_range.rb b/lib/gitlab/background_migration/normalize_ldap_extern_uids_range.rb index bc53e6d7f94..85749366bfd 100644 --- a/lib/gitlab/background_migration/normalize_ldap_extern_uids_range.rb +++ b/lib/gitlab/background_migration/normalize_ldap_extern_uids_range.rb @@ -1,3 +1,10 @@ +# frozen_string_literal: true +# rubocop:disable Metrics/MethodLength +# rubocop:disable Metrics/LineLength +# rubocop:disable Metrics/ClassLength +# rubocop:disable Metrics/BlockLength +# rubocop:disable Style/Documentation + module Gitlab module BackgroundMigration class NormalizeLdapExternUidsRange diff --git a/lib/gitlab/background_migration/populate_fork_networks_range.rb b/lib/gitlab/background_migration/populate_fork_networks_range.rb index 2ef3a207dd3..f8508b5fbdf 100644 --- a/lib/gitlab/background_migration/populate_fork_networks_range.rb +++ b/lib/gitlab/background_migration/populate_fork_networks_range.rb @@ -1,3 +1,8 @@ +# frozen_string_literal: true +# rubocop:disable Metrics/MethodLength +# rubocop:disable Metrics/LineLength +# rubocop:disable Style/Documentation + module Gitlab module BackgroundMigration class PopulateForkNetworksRange diff --git a/lib/gitlab/background_migration/populate_merge_requests_latest_merge_request_diff_id.rb b/lib/gitlab/background_migration/populate_merge_requests_latest_merge_request_diff_id.rb index 7e109e96e73..dcac355e1b0 100644 --- a/lib/gitlab/background_migration/populate_merge_requests_latest_merge_request_diff_id.rb +++ b/lib/gitlab/background_migration/populate_merge_requests_latest_merge_request_diff_id.rb @@ -1,3 +1,6 @@ +# frozen_string_literal: true +# rubocop:disable Style/Documentation + module Gitlab module BackgroundMigration class PopulateMergeRequestsLatestMergeRequestDiffId diff --git a/lib/gitlab/ee_compat_check.rb b/lib/gitlab/ee_compat_check.rb index 3a6165f504c..4a9d3e52fae 100644 --- a/lib/gitlab/ee_compat_check.rb +++ b/lib/gitlab/ee_compat_check.rb @@ -91,7 +91,7 @@ module Gitlab step( "Generating the patch against #{remote}/master in #{patch_path}", - %W[git diff --binary #{remote}/master...#{branch}] + %W[git diff --binary #{remote}/master...origin/#{branch}] ) do |output, status| throw(:halt_check, :ko) unless status.zero? @@ -102,7 +102,7 @@ module Gitlab end def ce_branch_compat_check! - if check_patch(ce_patch_full_path, remote: 'canonical-ce').zero? + if check_patch(ce_patch_full_path).zero? puts applies_cleanly_msg(ce_branch) throw(:halt_check) end @@ -129,7 +129,7 @@ module Gitlab end def ee_branch_compat_check! - unless check_patch(ee_patch_full_path, remote: 'canonical-ee').zero? + unless check_patch(ee_patch_full_path).zero? puts puts ee_branch_doesnt_apply_cleanly_msg @@ -140,9 +140,9 @@ module Gitlab puts applies_cleanly_msg(ee_branch_found) end - def check_patch(patch_path, remote:) + def check_patch(patch_path) step("Checking out master", %w[git checkout master]) - step("Resetting to latest master", %W[git reset --hard #{remote}/master]) + step("Resetting to latest master", %w[git reset --hard canonical-ee/master]) step( "Checking if #{patch_path} applies cleanly to EE/master", # Don't use --check here because it can result in a 0-exit status even @@ -182,7 +182,7 @@ module Gitlab def merge_base_found?(master_remote:, branch:) step( "Finding merge base with #{master_remote}/master", - %W[git merge-base #{master_remote}/master #{branch}] + %W[git merge-base #{master_remote}/master origin/#{branch}] ) do |output, status| if status.zero? puts "Merge base was found: #{output}" diff --git a/lib/gitlab/encoding_helper.rb b/lib/gitlab/encoding_helper.rb index 99dfee3dd9b..582028493e9 100644 --- a/lib/gitlab/encoding_helper.rb +++ b/lib/gitlab/encoding_helper.rb @@ -17,6 +17,10 @@ module Gitlab return nil unless message.respond_to?(:force_encoding) return message if message.encoding == Encoding::UTF_8 && message.valid_encoding? + if message.respond_to?(:frozen?) && message.frozen? + message = message.dup + end + message.force_encoding("UTF-8") return message if message.valid_encoding? diff --git a/lib/gitlab/git/repository.rb b/lib/gitlab/git/repository.rb index dcca20c75ef..ff408c0c4dd 100644 --- a/lib/gitlab/git/repository.rb +++ b/lib/gitlab/git/repository.rb @@ -1243,11 +1243,21 @@ module Gitlab sort_branches(branches, sort_by) end + # Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/695 def git_merged_branch_names(branch_names = []) - lines = run_git(['branch', '--merged', root_ref] + branch_names) - .first.lines + root_sha = find_branch(root_ref).target - lines.map(&:strip) + git_arguments = + %W[branch --merged #{root_sha} + --format=%(refname:short)\ %(objectname)] + branch_names + + lines = run_git(git_arguments).first.lines + + lines.each_with_object([]) do |line, branches| + name, sha = line.strip.split(' ', 2) + + branches << name if sha != root_sha + end end def log_using_shell?(options) diff --git a/lib/gitlab/git/user.rb b/lib/gitlab/git/user.rb index e6b61417de1..e573cd0e143 100644 --- a/lib/gitlab/git/user.rb +++ b/lib/gitlab/git/user.rb @@ -8,7 +8,12 @@ module Gitlab end def self.from_gitaly(gitaly_user) - new(gitaly_user.gl_username, gitaly_user.name, gitaly_user.email, gitaly_user.gl_id) + new( + gitaly_user.gl_username, + Gitlab::EncodingHelper.encode!(gitaly_user.name), + Gitlab::EncodingHelper.encode!(gitaly_user.email), + gitaly_user.gl_id + ) end def initialize(username, name, email, gl_id) @@ -23,7 +28,7 @@ module Gitlab end def to_gitaly - Gitaly::User.new(gl_username: username, gl_id: gl_id, name: name, email: email) + Gitaly::User.new(gl_username: username, gl_id: gl_id, name: name.b, email: email.b) end end end diff --git a/lib/gitlab/import_export/project_tree_restorer.rb b/lib/gitlab/import_export/project_tree_restorer.rb index 639f4f0c3f0..c518943be59 100644 --- a/lib/gitlab/import_export/project_tree_restorer.rb +++ b/lib/gitlab/import_export/project_tree_restorer.rb @@ -60,6 +60,8 @@ module Gitlab end end + @project.merge_requests.set_latest_merge_request_diff_ids! + @saved end diff --git a/lib/gitlab/metrics/prometheus.rb b/lib/gitlab/metrics/prometheus.rb index 09103b4ca2d..4f165d12a94 100644 --- a/lib/gitlab/metrics/prometheus.rb +++ b/lib/gitlab/metrics/prometheus.rb @@ -17,9 +17,9 @@ module Gitlab end def prometheus_metrics_enabled? - return @prometheus_metrics_enabled if defined?(@prometheus_metrics_enabled) - - @prometheus_metrics_enabled = prometheus_metrics_enabled_unmemoized + # force disable prometheus_metrics until + # https://gitlab.com/gitlab-org/prometheus-client-mmap/merge_requests/11 is ready + false end def registry diff --git a/lib/gitlab/path_regex.rb b/lib/gitlab/path_regex.rb index 9a91f8bf96a..7e5dfd33502 100644 --- a/lib/gitlab/path_regex.rb +++ b/lib/gitlab/path_regex.rb @@ -51,7 +51,6 @@ module Gitlab slash-command-logo.png snippets u - unicorn_test unsubscribes uploads users diff --git a/lib/gitlab/usage_data.rb b/lib/gitlab/usage_data.rb index 112d4939582..2adcc9809b3 100644 --- a/lib/gitlab/usage_data.rb +++ b/lib/gitlab/usage_data.rb @@ -79,7 +79,7 @@ module Gitlab def features_usage_data_ce { - signup: current_application_settings.signup_enabled?, + signup: current_application_settings.allow_signup?, ldap: Gitlab.config.ldap.enabled, gravatar: current_application_settings.gravatar_enabled?, omniauth: Gitlab.config.omniauth.enabled, diff --git a/lib/tasks/brakeman.rake b/lib/tasks/brakeman.rake index 99b3168d9eb..2301ec9b228 100644 --- a/lib/tasks/brakeman.rake +++ b/lib/tasks/brakeman.rake @@ -2,7 +2,7 @@ desc 'Security check via brakeman' task :brakeman do # We get 0 warnings at level 'w3' but we would like to reach 'w2'. Merge # requests are welcome! - if system(*%w(brakeman --no-progress --skip-files lib/backup/repository.rb,app/controllers/unicorn_test_controller.rb -w3 -z)) + if system(*%w(brakeman --no-progress --skip-files lib/backup/repository.rb -w3 -z)) puts 'Security check succeed' else puts 'Security check failed' diff --git a/package.json b/package.json index 16a6e45e820..8eb38f28cee 100644 --- a/package.json +++ b/package.json @@ -14,14 +14,14 @@ }, "dependencies": { "autosize": "^4.0.0", - "axios": "^0.16.2", + "axios": "^0.17.1", "axios-mock-adapter": "^1.10.0", - "babel-core": "^6.22.1", - "babel-eslint": "^7.2.1", - "babel-loader": "^7.1.1", - "babel-plugin-transform-define": "^1.2.0", - "babel-preset-latest": "^6.24.0", - "babel-preset-stage-2": "^6.22.0", + "babel-core": "^6.26.0", + "babel-eslint": "^8.0.2", + "babel-loader": "^7.1.2", + "babel-plugin-transform-define": "^1.3.0", + "babel-preset-latest": "^6.24.1", + "babel-preset-stage-2": "^6.24.1", "blackst0ne-mermaid": "^7.1.0-fixed", "bootstrap-sass": "^3.3.6", "brace-expansion": "^1.1.8", @@ -66,18 +66,18 @@ "underscore": "^1.8.3", "url-loader": "^0.5.8", "visibilityjs": "^1.2.4", - "vue": "^2.5.2", - "vue-loader": "^11.3.4", + "vue": "^2.5.8", + "vue-loader": "^13.5.0", "vue-resource": "^1.3.4", - "vue-template-compiler": "^2.5.2", - "vuex": "^3.0.0", + "vue-template-compiler": "^2.5.8", + "vuex": "^3.0.1", "webpack": "^3.5.5", "webpack-bundle-analyzer": "^2.8.2", "webpack-stats-plugin": "^0.1.5" }, "devDependencies": { "@gitlab-org/gitlab-svgs": "^1.0.2", - "babel-plugin-istanbul": "^4.0.0", + "babel-plugin-istanbul": "^4.1.5", "eslint": "^3.10.1", "eslint-config-airbnb-base": "^10.0.1", "eslint-import-resolver-webpack": "^0.8.3", diff --git a/scripts/prepare_build.sh b/scripts/prepare_build.sh index 36bcf087cd9..ea406aadf39 100644 --- a/scripts/prepare_build.sh +++ b/scripts/prepare_build.sh @@ -14,6 +14,7 @@ fi retry gem install knapsack cp config/gitlab.yml.example config/gitlab.yml +sed -i 's/bin_path: \/usr\/bin\/git/bin_path: \/usr\/local\/bin\/git/' config/gitlab.yml # Determine the database by looking at the job name. # For example, we'll get pg if the job is `rspec-pg 19 20` diff --git a/spec/controllers/application_controller_spec.rb b/spec/controllers/application_controller_spec.rb index 768c7e99c96..fe95d1ef9cd 100644 --- a/spec/controllers/application_controller_spec.rb +++ b/spec/controllers/application_controller_spec.rb @@ -41,14 +41,13 @@ describe ApplicationController do controller.send(:check_password_expiration) end - it 'redirects if the user is over their password expiry and sign-in is disabled' do - stub_application_setting(password_authentication_enabled: false) + it 'does not redirect if the user is over their password expiry but password authentication is disabled for the web interface' do + stub_application_setting(password_authentication_enabled_for_web: false) + stub_application_setting(password_authentication_enabled_for_git: false) user.password_expires_at = Time.new(2002) - expect(user.ldap_user?).to be_falsey allow(controller).to receive(:current_user).and_return(user) - expect(controller).to receive(:redirect_to) - expect(controller).to receive(:new_profile_password_path) + expect(controller).not_to receive(:redirect_to) controller.send(:check_password_expiration) end diff --git a/spec/controllers/passwords_controller_spec.rb b/spec/controllers/passwords_controller_spec.rb index 8778bff1190..4d31cfedbd2 100644 --- a/spec/controllers/passwords_controller_spec.rb +++ b/spec/controllers/passwords_controller_spec.rb @@ -1,18 +1,20 @@ require 'spec_helper' describe PasswordsController do - describe '#prevent_ldap_reset' do + describe '#check_password_authentication_available' do before do @request.env["devise.mapping"] = Devise.mappings[:user] end - context 'when password authentication is disabled' do - it 'allows password reset' do - stub_application_setting(password_authentication_enabled: false) + context 'when password authentication is disabled for the web interface and Git' do + it 'prevents a password reset' do + stub_application_setting(password_authentication_enabled_for_web: false) + stub_application_setting(password_authentication_enabled_for_git: false) post :create expect(response).to have_gitlab_http_status(302) + expect(flash[:alert]).to eq 'Password authentication is unavailable.' end end @@ -22,7 +24,7 @@ describe PasswordsController do it 'prevents a password reset' do post :create, user: { email: user.email } - expect(flash[:alert]).to eq('Cannot reset password for LDAP user.') + expect(flash[:alert]).to eq 'Password authentication is unavailable.' end end end diff --git a/spec/controllers/registrations_controller_spec.rb b/spec/controllers/registrations_controller_spec.rb index 1d3ddfbd220..346944fd5b0 100644 --- a/spec/controllers/registrations_controller_spec.rb +++ b/spec/controllers/registrations_controller_spec.rb @@ -118,7 +118,8 @@ describe RegistrationsController do context 'user does not require password confirmation' do before do - stub_application_setting(password_authentication_enabled: false) + stub_application_setting(password_authentication_enabled_for_web: false) + stub_application_setting(password_authentication_enabled_for_git: false) end it 'fails if username confirmation is not provided' do diff --git a/spec/features/profiles/password_spec.rb b/spec/features/profiles/password_spec.rb index fb4355074df..4665626f114 100644 --- a/spec/features/profiles/password_spec.rb +++ b/spec/features/profiles/password_spec.rb @@ -53,12 +53,13 @@ describe 'Profile > Password' do context 'Regular user' do let(:user) { create(:user) } - it 'renders 200 when sign-in is disabled' do - stub_application_setting(password_authentication_enabled: false) + it 'renders 404 when password authentication is disabled for the web interface and Git' do + stub_application_setting(password_authentication_enabled_for_web: false) + stub_application_setting(password_authentication_enabled_for_git: false) visit edit_profile_password_path - expect(page).to have_gitlab_http_status(200) + expect(page).to have_gitlab_http_status(404) end end diff --git a/spec/features/projects/blobs/blob_show_spec.rb b/spec/features/projects/blobs/blob_show_spec.rb index 3d465e709b9..88813d9b5ff 100644 --- a/spec/features/projects/blobs/blob_show_spec.rb +++ b/spec/features/projects/blobs/blob_show_spec.rb @@ -1,6 +1,8 @@ require 'spec_helper' feature 'File blob', :js do + include MobileHelpers + let(:project) { create(:project, :public, :repository) } def visit_blob(path, anchor: nil, ref: 'master') @@ -30,6 +32,16 @@ feature 'File blob', :js do expect(page).to have_link('Open raw') end end + + it 'displays file actions on all screen sizes' do + file_actions_selector = '.file-actions' + + resize_screen_sm + expect(page).to have_selector(file_actions_selector, visible: true) + + resize_screen_xs + expect(page).to have_selector(file_actions_selector, visible: true) + end end context 'Markdown file' do diff --git a/spec/features/projects/environments/environments_spec.rb b/spec/features/projects/environments/environments_spec.rb index b4eb5795470..879ee6f4b9b 100644 --- a/spec/features/projects/environments/environments_spec.rb +++ b/spec/features/projects/environments/environments_spec.rb @@ -14,8 +14,10 @@ feature 'Environments page', :js do it 'shows "Available" and "Stopped" tab with links' do visit_environments(project) - expect(page).to have_link('Available') - expect(page).to have_link('Stopped') + expect(page).to have_selector('.js-environments-tab-available') + expect(page).to have_content('Available') + expect(page).to have_selector('.js-environments-tab-stopped') + expect(page).to have_content('Stopped') end describe 'with one available environment' do @@ -75,8 +77,8 @@ feature 'Environments page', :js do it 'does not show environments and counters are set to zero' do expect(page).to have_content('You don\'t have any environments right now.') - expect(page.find('.js-available-environments-count').text).to eq('0') - expect(page.find('.js-stopped-environments-count').text).to eq('0') + expect(page.find('.js-environments-tab-available .badge').text).to eq('0') + expect(page.find('.js-environments-tab-stopped .badge').text).to eq('0') end end @@ -93,8 +95,8 @@ feature 'Environments page', :js do it 'shows environments names and counters' do expect(page).to have_link(environment.name) - expect(page.find('.js-available-environments-count').text).to eq('1') - expect(page.find('.js-stopped-environments-count').text).to eq('0') + expect(page.find('.js-environments-tab-available .badge').text).to eq('1') + expect(page.find('.js-environments-tab-stopped .badge').text).to eq('0') end it 'does not show deployments' do @@ -294,11 +296,32 @@ feature 'Environments page', :js do end end + describe 'environments folders view' do + before do + create(:environment, project: project, + name: 'staging.review/review-1', + state: :available) + create(:environment, project: project, + name: 'staging.review/review-2', + state: :available) + end + + scenario 'user opens folder view' do + visit folder_project_environments_path(project, 'staging.review') + wait_for_requests + + expect(page).to have_content('Environments / staging.review') + expect(page).to have_content('review-1') + expect(page).to have_content('review-2') + end + end + def have_terminal_button have_link(nil, href: terminal_project_environment_path(project, environment)) end def visit_environments(project, **opts) visit project_environments_path(project, **opts) + wait_for_requests end end diff --git a/spec/features/projects/no_password_spec.rb b/spec/features/projects/no_password_spec.rb index 6aff079dd39..b3b3212556c 100644 --- a/spec/features/projects/no_password_spec.rb +++ b/spec/features/projects/no_password_spec.rb @@ -30,7 +30,7 @@ feature 'No Password Alert' do let(:user) { create(:omniauth_user, extern_uid: 'my-uid', provider: 'saml') } before do - stub_application_setting(password_authentication_enabled?: false) + stub_application_setting(password_authentication_enabled_for_git?: false) stub_omniauth_saml_config(enabled: true, auto_link_saml_user: true, allow_single_sign_on: ['saml'], providers: [mock_saml_config]) end diff --git a/spec/helpers/button_helper_spec.rb b/spec/helpers/button_helper_spec.rb index 4423560ecaa..e5158761333 100644 --- a/spec/helpers/button_helper_spec.rb +++ b/spec/helpers/button_helper_spec.rb @@ -35,7 +35,7 @@ describe ButtonHelper do context 'with internal auth disabled' do before do - stub_application_setting(password_authentication_enabled?: false) + stub_application_setting(password_authentication_enabled_for_git?: false) end context 'when user has no personal access tokens' do diff --git a/spec/helpers/projects_helper_spec.rb b/spec/helpers/projects_helper_spec.rb index 5777b5c4025..ede9d232efd 100644 --- a/spec/helpers/projects_helper_spec.rb +++ b/spec/helpers/projects_helper_spec.rb @@ -150,17 +150,26 @@ describe ProjectsHelper do end end - context 'user requires a password' do - let(:user) { create(:user, password_automatically_set: true) } + context 'user has hidden the message' do + it 'returns false' do + allow(helper).to receive(:cookies).and_return(hide_no_password_message: true) + + expect(helper.show_no_password_message?).to be_falsey + end + end + context 'user requires a password for Git' do it 'returns true' do + allow(user).to receive(:require_password_creation_for_git?).and_return(true) + expect(helper.show_no_password_message?).to be_truthy end end - context 'user requires a personal access token' do + context 'user requires a personal access token for Git' do it 'returns true' do - stub_application_setting(password_authentication_enabled?: false) + allow(user).to receive(:require_password_creation_for_git?).and_return(false) + allow(user).to receive(:require_personal_access_token_creation_for_git_auth?).and_return(true) expect(helper.show_no_password_message?).to be_truthy end @@ -168,23 +177,23 @@ describe ProjectsHelper do end describe '#link_to_set_password' do + let(:user) { create(:user, password_automatically_set: true) } + before do allow(helper).to receive(:current_user).and_return(user) end - context 'user requires a password' do - let(:user) { create(:user, password_automatically_set: true) } - + context 'password authentication is enabled for Git' do it 'returns link to set a password' do + stub_application_setting(password_authentication_enabled_for_git?: true) + expect(helper.link_to_set_password).to match %r{<a href="#{edit_profile_password_path}">set a password</a>} end end - context 'user requires a personal access token' do - let(:user) { create(:user) } - + context 'password authentication is disabled for Git' do it 'returns link to create a personal access token' do - stub_application_setting(password_authentication_enabled?: false) + stub_application_setting(password_authentication_enabled_for_git?: false) expect(helper.link_to_set_password).to match %r{<a href="#{profile_personal_access_tokens_path}">create a personal access token</a>} end diff --git a/spec/javascripts/environments/emtpy_state_spec.js b/spec/javascripts/environments/emtpy_state_spec.js new file mode 100644 index 00000000000..82de35933f5 --- /dev/null +++ b/spec/javascripts/environments/emtpy_state_spec.js @@ -0,0 +1,57 @@ + +import Vue from 'vue'; +import emptyState from '~/environments/components/empty_state.vue'; +import mountComponent from '../helpers/vue_mount_component_helper'; + +describe('environments empty state', () => { + let vm; + let Component; + + beforeEach(() => { + Component = Vue.extend(emptyState); + }); + + afterEach(() => { + vm.$destroy(); + }); + + describe('With permissions', () => { + beforeEach(() => { + vm = mountComponent(Component, { + newPath: 'foo', + canCreateEnvironment: true, + helpPath: 'bar', + }); + }); + + it('renders empty state and new environment button', () => { + expect( + vm.$el.querySelector('.js-blank-state-title').textContent.trim(), + ).toEqual('You don\'t have any environments right now.'); + + expect( + vm.$el.querySelector('.js-new-environment-button').getAttribute('href'), + ).toEqual('foo'); + }); + }); + + describe('Without permission', () => { + beforeEach(() => { + vm = mountComponent(Component, { + newPath: 'foo', + canCreateEnvironment: false, + helpPath: 'bar', + }); + }); + + it('renders empty state without new button', () => { + expect( + vm.$el.querySelector('.js-blank-state-title').textContent.trim(), + ).toEqual('You don\'t have any environments right now.'); + + expect( + vm.$el.querySelector('.js-new-environment-button'), + ).toBeNull(); + }); + }); +}); diff --git a/spec/javascripts/environments/environment_table_spec.js b/spec/javascripts/environments/environment_table_spec.js index 2862971bec4..9bd42863759 100644 --- a/spec/javascripts/environments/environment_table_spec.js +++ b/spec/javascripts/environments/environment_table_spec.js @@ -1,10 +1,17 @@ import Vue from 'vue'; import environmentTableComp from '~/environments/components/environments_table.vue'; +import mountComponent from '../helpers/vue_mount_component_helper'; + +describe('Environment table', () => { + let Component; + let vm; -describe('Environment item', () => { - preloadFixtures('static/environments/element.html.raw'); beforeEach(() => { - loadFixtures('static/environments/element.html.raw'); + Component = Vue.extend(environmentTableComp); + }); + + afterEach(() => { + vm.$destroy(); }); it('Should render a table', () => { @@ -17,18 +24,12 @@ describe('Environment item', () => { }, }; - const EnvironmentTable = Vue.extend(environmentTableComp); - - const component = new EnvironmentTable({ - el: document.querySelector('.test-dom-element'), - propsData: { - environments: [{ mockItem }], - canCreateDeployment: false, - canReadEnvironment: true, - service: {}, - }, - }).$mount(); + vm = mountComponent(Component, { + environments: [mockItem], + canCreateDeployment: false, + canReadEnvironment: true, + }); - expect(component.$el.getAttribute('class')).toContain('ci-table'); + expect(vm.$el.getAttribute('class')).toContain('ci-table'); }); }); diff --git a/spec/javascripts/environments/environment_spec.js b/spec/javascripts/environments/environments_app_spec.js index 0c8817a8148..d02adb25b4e 100644 --- a/spec/javascripts/environments/environment_spec.js +++ b/spec/javascripts/environments/environments_app_spec.js @@ -1,18 +1,24 @@ import Vue from 'vue'; -import '~/flash'; -import environmentsComponent from '~/environments/components/environment.vue'; +import environmentsComponent from '~/environments/components/environments_app.vue'; import { environment, folder } from './mock_data'; import { headersInterceptor } from '../helpers/vue_resource_helper'; +import mountComponent from '../helpers/vue_mount_component_helper'; describe('Environment', () => { - preloadFixtures('static/environments/environments.html.raw'); + const mockData = { + endpoint: 'environments.json', + canCreateEnvironment: true, + canCreateDeployment: true, + canReadEnvironment: true, + cssContainerClass: 'container', + newEnvironmentPath: 'environments/new', + helpPagePath: 'help', + }; let EnvironmentsComponent; let component; beforeEach(() => { - loadFixtures('static/environments/environments.html.raw'); - EnvironmentsComponent = Vue.extend(environmentsComponent); }); @@ -37,9 +43,7 @@ describe('Environment', () => { }); it('should render the empty state', (done) => { - component = new EnvironmentsComponent({ - el: document.querySelector('#environments-list-view'), - }); + component = mountComponent(EnvironmentsComponent, mockData); setTimeout(() => { expect( @@ -81,9 +85,7 @@ describe('Environment', () => { beforeEach(() => { Vue.http.interceptors.push(environmentsResponseInterceptor); Vue.http.interceptors.push(headersInterceptor); - component = new EnvironmentsComponent({ - el: document.querySelector('#environments-list-view'), - }); + component = mountComponent(EnvironmentsComponent, mockData); }); afterEach(() => { @@ -95,7 +97,7 @@ describe('Environment', () => { it('should render a table with environments', (done) => { setTimeout(() => { - expect(component.$el.querySelectorAll('table')).toBeDefined(); + expect(component.$el.querySelectorAll('table')).not.toBeNull(); expect( component.$el.querySelector('.environment-name').textContent.trim(), ).toEqual(environment.name); @@ -104,10 +106,6 @@ describe('Environment', () => { }); describe('pagination', () => { - afterEach(() => { - window.history.pushState({}, null, ''); - }); - it('should render pagination', (done) => { setTimeout(() => { expect( @@ -117,46 +115,23 @@ describe('Environment', () => { }, 0); }); - it('should update url when no search params are present', (done) => { - spyOn(gl.utils, 'visitUrl'); + it('should make an API request when page is clicked', (done) => { + spyOn(component, 'updateContent'); setTimeout(() => { component.$el.querySelector('.gl-pagination li:nth-child(5) a').click(); - expect(gl.utils.visitUrl).toHaveBeenCalledWith('?page=2'); + expect(component.updateContent).toHaveBeenCalledWith({ scope: 'available', page: '2' }); done(); }, 0); }); - it('should update url when page is already present', (done) => { - spyOn(gl.utils, 'visitUrl'); - window.history.pushState({}, null, '?page=1'); - - setTimeout(() => { - component.$el.querySelector('.gl-pagination li:nth-child(5) a').click(); - expect(gl.utils.visitUrl).toHaveBeenCalledWith('?page=2'); - done(); - }, 0); - }); - - it('should update url when page and scope are already present', (done) => { - spyOn(gl.utils, 'visitUrl'); - window.history.pushState({}, null, '?scope=all&page=1'); - + it('should make an API request when using tabs', (done) => { setTimeout(() => { - component.$el.querySelector('.gl-pagination li:nth-child(5) a').click(); - expect(gl.utils.visitUrl).toHaveBeenCalledWith('?scope=all&page=2'); - done(); - }, 0); - }); + spyOn(component, 'updateContent'); + component.$el.querySelector('.js-environments-tab-stopped').click(); - it('should update url when page and scope are already present and page is first param', (done) => { - spyOn(gl.utils, 'visitUrl'); - window.history.pushState({}, null, '?page=1&scope=all'); - - setTimeout(() => { - component.$el.querySelector('.gl-pagination li:nth-child(5) a').click(); - expect(gl.utils.visitUrl).toHaveBeenCalledWith('?page=2&scope=all'); + expect(component.updateContent).toHaveBeenCalledWith({ scope: 'stopped', page: '1' }); done(); - }, 0); + }); }); }); }); @@ -180,9 +155,7 @@ describe('Environment', () => { }); it('should render empty state', (done) => { - component = new EnvironmentsComponent({ - el: document.querySelector('#environments-list-view'), - }); + component = mountComponent(EnvironmentsComponent, mockData); setTimeout(() => { expect( @@ -214,9 +187,7 @@ describe('Environment', () => { beforeEach(() => { Vue.http.interceptors.push(environmentsResponseInterceptor); - component = new EnvironmentsComponent({ - el: document.querySelector('#environments-list-view'), - }); + component = mountComponent(EnvironmentsComponent, mockData); }); afterEach(() => { @@ -289,4 +260,59 @@ describe('Environment', () => { }); }); }); + + describe('methods', () => { + const environmentsEmptyResponseInterceptor = (request, next) => { + next(request.respondWith(JSON.stringify([]), { + status: 200, + })); + }; + + beforeEach(() => { + Vue.http.interceptors.push(environmentsEmptyResponseInterceptor); + Vue.http.interceptors.push(headersInterceptor); + + component = mountComponent(EnvironmentsComponent, mockData); + spyOn(history, 'pushState').and.stub(); + }); + + afterEach(() => { + Vue.http.interceptors = _.without( + Vue.http.interceptors, environmentsEmptyResponseInterceptor, + ); + Vue.http.interceptors = _.without(Vue.http.interceptors, headersInterceptor); + }); + + describe('updateContent', () => { + it('should set given parameters', (done) => { + component.updateContent({ scope: 'stopped', page: '3' }) + .then(() => { + expect(component.page).toEqual('3'); + expect(component.scope).toEqual('stopped'); + expect(component.requestData.scope).toEqual('stopped'); + expect(component.requestData.page).toEqual('3'); + done(); + }) + .catch(done.fail); + }); + }); + + describe('onChangeTab', () => { + it('should set page to 1', () => { + spyOn(component, 'updateContent'); + component.onChangeTab('stopped'); + + expect(component.updateContent).toHaveBeenCalledWith({ scope: 'stopped', page: '1' }); + }); + }); + + describe('onChangePage', () => { + it('should update page and keep scope', () => { + spyOn(component, 'updateContent'); + component.onChangePage(4); + + expect(component.updateContent).toHaveBeenCalledWith({ scope: component.scope, page: '4' }); + }); + }); + }); }); diff --git a/spec/javascripts/environments/folder/environments_folder_view_spec.js b/spec/javascripts/environments/folder/environments_folder_view_spec.js index 7e62d356bd2..4ea4d9d7499 100644 --- a/spec/javascripts/environments/folder/environments_folder_view_spec.js +++ b/spec/javascripts/environments/folder/environments_folder_view_spec.js @@ -1,25 +1,28 @@ import Vue from 'vue'; -import '~/flash'; import environmentsFolderViewComponent from '~/environments/folder/environments_folder_view.vue'; import { environmentsList } from '../mock_data'; import { headersInterceptor } from '../../helpers/vue_resource_helper'; +import mountComponent from '../../helpers/vue_mount_component_helper'; describe('Environments Folder View', () => { - preloadFixtures('static/environments/environments_folder_view.html.raw'); - let EnvironmentsFolderViewComponent; + let Component; + let component; + const mockData = { + endpoint: 'environments.json', + folderName: 'review', + canCreateDeployment: true, + canReadEnvironment: true, + cssContainerClass: 'container', + }; beforeEach(() => { - loadFixtures('static/environments/environments_folder_view.html.raw'); - EnvironmentsFolderViewComponent = Vue.extend(environmentsFolderViewComponent); - window.history.pushState({}, null, 'environments/folders/build'); + Component = Vue.extend(environmentsFolderViewComponent); }); afterEach(() => { - window.history.pushState({}, null, '/'); + component.$destroy(); }); - let component; - describe('successfull request', () => { const environmentsResponseInterceptor = (request, next) => { next(request.respondWith(JSON.stringify({ @@ -31,10 +34,10 @@ describe('Environments Folder View', () => { headers: { 'X-nExt-pAge': '2', 'x-page': '1', - 'X-Per-Page': '1', + 'X-Per-Page': '2', 'X-Prev-Page': '', - 'X-TOTAL': '37', - 'X-Total-Pages': '2', + 'X-TOTAL': '20', + 'X-Total-Pages': '10', }, })); }; @@ -43,9 +46,7 @@ describe('Environments Folder View', () => { Vue.http.interceptors.push(environmentsResponseInterceptor); Vue.http.interceptors.push(headersInterceptor); - component = new EnvironmentsFolderViewComponent({ - el: document.querySelector('#environments-folder-list-view'), - }); + component = mountComponent(Component, mockData); }); afterEach(() => { @@ -57,7 +58,7 @@ describe('Environments Folder View', () => { it('should render a table with environments', (done) => { setTimeout(() => { - expect(component.$el.querySelectorAll('table')).toBeDefined(); + expect(component.$el.querySelectorAll('table')).not.toBeNull(); expect( component.$el.querySelector('.environment-name').textContent.trim(), ).toEqual(environmentsList[0].name); @@ -68,11 +69,11 @@ describe('Environments Folder View', () => { it('should render available tab with count', (done) => { setTimeout(() => { expect( - component.$el.querySelector('.js-available-environments-folder-tab').textContent, + component.$el.querySelector('.js-environments-tab-available').textContent, ).toContain('Available'); expect( - component.$el.querySelector('.js-available-environments-folder-tab .js-available-environments-count').textContent, + component.$el.querySelector('.js-environments-tab-available .badge').textContent, ).toContain('0'); done(); }, 0); @@ -81,11 +82,11 @@ describe('Environments Folder View', () => { it('should render stopped tab with count', (done) => { setTimeout(() => { expect( - component.$el.querySelector('.js-stopped-environments-folder-tab').textContent, + component.$el.querySelector('.js-environments-tab-stopped').textContent, ).toContain('Stopped'); expect( - component.$el.querySelector('.js-stopped-environments-folder-tab .js-stopped-environments-count').textContent, + component.$el.querySelector('.js-environments-tab-stopped .badge').textContent, ).toContain('1'); done(); }, 0); @@ -94,8 +95,8 @@ describe('Environments Folder View', () => { it('should render parent folder name', (done) => { setTimeout(() => { expect( - component.$el.querySelector('.js-folder-name').textContent, - ).toContain('Environments / build'); + component.$el.querySelector('.js-folder-name').textContent.trim(), + ).toContain('Environments / review'); done(); }, 0); }); @@ -104,52 +105,30 @@ describe('Environments Folder View', () => { it('should render pagination', (done) => { setTimeout(() => { expect( - component.$el.querySelectorAll('.gl-pagination li').length, - ).toEqual(5); + component.$el.querySelectorAll('.gl-pagination'), + ).not.toBeNull(); done(); }, 0); }); - it('should update url when no search params are present', (done) => { - spyOn(gl.utils, 'visitUrl'); + it('should make an API request when changing page', (done) => { + spyOn(component, 'updateContent'); setTimeout(() => { - component.$el.querySelector('.gl-pagination li:nth-child(5) a').click(); - expect(gl.utils.visitUrl).toHaveBeenCalledWith('?page=2'); - done(); - }, 0); - }); - - it('should update url when page is already present', (done) => { - spyOn(gl.utils, 'visitUrl'); - window.history.pushState({}, null, '?page=1'); + component.$el.querySelector('.gl-pagination .js-last-button a').click(); - setTimeout(() => { - component.$el.querySelector('.gl-pagination li:nth-child(5) a').click(); - expect(gl.utils.visitUrl).toHaveBeenCalledWith('?page=2'); + expect(component.updateContent).toHaveBeenCalledWith({ scope: component.scope, page: '10' }); done(); }, 0); }); - it('should update url when page and scope are already present', (done) => { - spyOn(gl.utils, 'visitUrl'); - window.history.pushState({}, null, '?scope=all&page=1'); - + it('should make an API request when using tabs', (done) => { setTimeout(() => { - component.$el.querySelector('.gl-pagination li:nth-child(5) a').click(); - expect(gl.utils.visitUrl).toHaveBeenCalledWith('?scope=all&page=2'); - done(); - }, 0); - }); - - it('should update url when page and scope are already present and page is first param', (done) => { - spyOn(gl.utils, 'visitUrl'); - window.history.pushState({}, null, '?page=1&scope=all'); + spyOn(component, 'updateContent'); + component.$el.querySelector('.js-environments-tab-stopped').click(); - setTimeout(() => { - component.$el.querySelector('.gl-pagination li:nth-child(5) a').click(); - expect(gl.utils.visitUrl).toHaveBeenCalledWith('?page=2&scope=all'); + expect(component.updateContent).toHaveBeenCalledWith({ scope: 'stopped', page: '1' }); done(); - }, 0); + }); }); }); }); @@ -172,9 +151,7 @@ describe('Environments Folder View', () => { }); it('should not render a table', (done) => { - component = new EnvironmentsFolderViewComponent({ - el: document.querySelector('#environments-folder-list-view'), - }); + component = mountComponent(Component, mockData); setTimeout(() => { expect( @@ -187,11 +164,11 @@ describe('Environments Folder View', () => { it('should render available tab with count 0', (done) => { setTimeout(() => { expect( - component.$el.querySelector('.js-available-environments-folder-tab').textContent, + component.$el.querySelector('.js-environments-tab-available').textContent, ).toContain('Available'); expect( - component.$el.querySelector('.js-available-environments-folder-tab .js-available-environments-count').textContent, + component.$el.querySelector('.js-environments-tab-available .badge').textContent, ).toContain('0'); done(); }, 0); @@ -200,14 +177,70 @@ describe('Environments Folder View', () => { it('should render stopped tab with count 0', (done) => { setTimeout(() => { expect( - component.$el.querySelector('.js-stopped-environments-folder-tab').textContent, + component.$el.querySelector('.js-environments-tab-stopped').textContent, ).toContain('Stopped'); expect( - component.$el.querySelector('.js-stopped-environments-folder-tab .js-stopped-environments-count').textContent, + component.$el.querySelector('.js-environments-tab-stopped .badge').textContent, ).toContain('0'); done(); }, 0); }); }); + + describe('methods', () => { + const environmentsEmptyResponseInterceptor = (request, next) => { + next(request.respondWith(JSON.stringify([]), { + status: 200, + })); + }; + + beforeEach(() => { + Vue.http.interceptors.push(environmentsEmptyResponseInterceptor); + Vue.http.interceptors.push(headersInterceptor); + + component = mountComponent(Component, mockData); + spyOn(history, 'pushState').and.stub(); + }); + + afterEach(() => { + Vue.http.interceptors = _.without( + Vue.http.interceptors, environmentsEmptyResponseInterceptor, + ); + Vue.http.interceptors = _.without(Vue.http.interceptors, headersInterceptor); + }); + + describe('updateContent', () => { + it('should set given parameters', (done) => { + component.updateContent({ scope: 'stopped', page: '4' }) + .then(() => { + expect(component.page).toEqual('4'); + expect(component.scope).toEqual('stopped'); + expect(component.requestData.scope).toEqual('stopped'); + expect(component.requestData.page).toEqual('4'); + done(); + }) + .catch(done.fail); + }); + }); + + describe('onChangeTab', () => { + it('should set page to 1', () => { + spyOn(component, 'updateContent'); + component.onChangeTab('stopped'); + + expect(component.updateContent).toHaveBeenCalledWith({ scope: 'stopped', page: '1' }); + }); + }); + + describe('onChangePage', () => { + it('should update page and keep scope', () => { + spyOn(component, 'updateContent'); + + component.onChangePage(4); + + expect(component.updateContent).toHaveBeenCalledWith({ scope: component.scope, page: '4' }); + }); + }); + }); }); diff --git a/spec/javascripts/fixtures/environments/element.html.haml b/spec/javascripts/fixtures/environments/element.html.haml deleted file mode 100644 index 8d7aeb23356..00000000000 --- a/spec/javascripts/fixtures/environments/element.html.haml +++ /dev/null @@ -1 +0,0 @@ -.test-dom-element diff --git a/spec/javascripts/fixtures/environments/environments.html.haml b/spec/javascripts/fixtures/environments/environments.html.haml deleted file mode 100644 index e6000fbb553..00000000000 --- a/spec/javascripts/fixtures/environments/environments.html.haml +++ /dev/null @@ -1,9 +0,0 @@ -%div - #environments-list-view{ data: { environments_data: "foo/environments", - "can-create-deployment" => "true", - "can-read-environment" => "true", - "can-create-environment" => "true", - "project-environments-path" => "https://gitlab.com/foo/environments", - "project-stopped-environments-path" => "https://gitlab.com/foo/environments?scope=stopped", - "new-environment-path" => "https://gitlab.com/foo/environments/new", - "help-page-path" => "https://gitlab.com/help_page"}} diff --git a/spec/javascripts/fixtures/environments/environments_folder_view.html.haml b/spec/javascripts/fixtures/environments/environments_folder_view.html.haml deleted file mode 100644 index aceec139730..00000000000 --- a/spec/javascripts/fixtures/environments/environments_folder_view.html.haml +++ /dev/null @@ -1,7 +0,0 @@ -%div - #environments-folder-list-view{ data: { "can-create-deployment" => "true", - "can-read-environment" => "true", - "css-class" => "", - "commit-icon-svg" => custom_icon("icon_commit"), - "terminal-icon-svg" => custom_icon("icon_terminal"), - "play-icon-svg" => custom_icon("icon_play") } } diff --git a/spec/javascripts/lib/utils/common_utils_spec.js b/spec/javascripts/lib/utils/common_utils_spec.js index 6dad5d6b6bd..0a9d815f469 100644 --- a/spec/javascripts/lib/utils/common_utils_spec.js +++ b/spec/javascripts/lib/utils/common_utils_spec.js @@ -142,47 +142,6 @@ describe('common_utils', () => { }); }); - describe('setParamInURL', () => { - afterEach(() => { - window.history.pushState({}, null, ''); - }); - - it('should return the parameter', () => { - window.history.replaceState({}, null, ''); - - expect(commonUtils.setParamInURL('page', 156)).toBe('?page=156'); - expect(commonUtils.setParamInURL('page', '156')).toBe('?page=156'); - }); - - it('should update the existing parameter when its a number', () => { - window.history.pushState({}, null, '?page=15'); - - expect(commonUtils.setParamInURL('page', 16)).toBe('?page=16'); - expect(commonUtils.setParamInURL('page', '16')).toBe('?page=16'); - expect(commonUtils.setParamInURL('page', true)).toBe('?page=true'); - }); - - it('should update the existing parameter when its a string', () => { - window.history.pushState({}, null, '?scope=all'); - - expect(commonUtils.setParamInURL('scope', 'finished')).toBe('?scope=finished'); - }); - - it('should update the existing parameter when more than one parameter exists', () => { - window.history.pushState({}, null, '?scope=all&page=15'); - - expect(commonUtils.setParamInURL('scope', 'finished')).toBe('?scope=finished&page=15'); - }); - - it('should add a new parameter to the end of the existing ones', () => { - window.history.pushState({}, null, '?scope=all'); - - expect(commonUtils.setParamInURL('page', 16)).toBe('?scope=all&page=16'); - expect(commonUtils.setParamInURL('page', '16')).toBe('?scope=all&page=16'); - expect(commonUtils.setParamInURL('page', true)).toBe('?scope=all&page=true'); - }); - }); - describe('historyPushState', () => { afterEach(() => { window.history.replaceState({}, null, null); diff --git a/spec/javascripts/pipelines/pipelines_spec.js b/spec/javascripts/pipelines/pipelines_spec.js index ff38bc1974d..367b42cefb0 100644 --- a/spec/javascripts/pipelines/pipelines_spec.js +++ b/spec/javascripts/pipelines/pipelines_spec.js @@ -176,45 +176,49 @@ describe('Pipelines', () => { }); }); - describe('updateContent', () => { - it('should set given parameters', () => { - component = mountComponent(PipelinesComponent, { - store: new Store(), - }); - component.updateContent({ scope: 'finished', page: '4' }); - - expect(component.page).toEqual('4'); - expect(component.scope).toEqual('finished'); - expect(component.requestData.scope).toEqual('finished'); - expect(component.requestData.page).toEqual('4'); + describe('methods', () => { + beforeEach(() => { + spyOn(history, 'pushState').and.stub(); }); - }); - describe('onChangeTab', () => { - it('should set page to 1', () => { - component = mountComponent(PipelinesComponent, { - store: new Store(), - }); + describe('updateContent', () => { + it('should set given parameters', () => { + component = mountComponent(PipelinesComponent, { + store: new Store(), + }); + component.updateContent({ scope: 'finished', page: '4' }); - spyOn(component, 'updateContent'); + expect(component.page).toEqual('4'); + expect(component.scope).toEqual('finished'); + expect(component.requestData.scope).toEqual('finished'); + expect(component.requestData.page).toEqual('4'); + }); + }); - component.onChangeTab('running'); + describe('onChangeTab', () => { + it('should set page to 1', () => { + component = mountComponent(PipelinesComponent, { + store: new Store(), + }); + spyOn(component, 'updateContent'); - expect(component.updateContent).toHaveBeenCalledWith({ scope: 'running', page: '1' }); - }); - }); + component.onChangeTab('running'); - describe('onChangePage', () => { - it('should update page and keep scope', () => { - component = mountComponent(PipelinesComponent, { - store: new Store(), + expect(component.updateContent).toHaveBeenCalledWith({ scope: 'running', page: '1' }); }); + }); - spyOn(component, 'updateContent'); + describe('onChangePage', () => { + it('should update page and keep scope', () => { + component = mountComponent(PipelinesComponent, { + store: new Store(), + }); + spyOn(component, 'updateContent'); - component.onChangePage(4); + component.onChangePage(4); - expect(component.updateContent).toHaveBeenCalledWith({ scope: component.scope, page: '4' }); + expect(component.updateContent).toHaveBeenCalledWith({ scope: component.scope, page: '4' }); + }); }); }); }); diff --git a/spec/javascripts/pipelines/navigation_tabs_spec.js b/spec/javascripts/vue_shared/components/navigation_tabs_spec.js index f125a2fa189..78e7d747b92 100644 --- a/spec/javascripts/pipelines/navigation_tabs_spec.js +++ b/spec/javascripts/vue_shared/components/navigation_tabs_spec.js @@ -1,8 +1,8 @@ import Vue from 'vue'; -import navigationTabs from '~/pipelines/components/navigation_tabs.vue'; -import mountComponent from '../helpers/vue_mount_component_helper'; +import navigationTabs from '~/vue_shared/components/navigation_tabs.vue'; +import mountComponent from '../../helpers/vue_mount_component_helper'; -describe('navigation tabs pipeline component', () => { +describe('navigation tabs component', () => { let vm; let Component; let data; @@ -29,7 +29,7 @@ describe('navigation tabs pipeline component', () => { ]; Component = Vue.extend(navigationTabs); - vm = mountComponent(Component, { tabs: data }); + vm = mountComponent(Component, { tabs: data, scope: 'pipelines' }); }); afterEach(() => { @@ -52,4 +52,10 @@ describe('navigation tabs pipeline component', () => { it('should not render badge', () => { expect(vm.$el.querySelector('.js-pipelines-tab-running .badge')).toEqual(null); }); + + it('should trigger onTabClick', () => { + spyOn(vm, '$emit'); + vm.$el.querySelector('.js-pipelines-tab-pending').click(); + expect(vm.$emit).toHaveBeenCalledWith('onChangeTab', 'pending'); + }); }); diff --git a/spec/lib/banzai/filter/issue_reference_filter_spec.rb b/spec/lib/banzai/filter/issue_reference_filter_spec.rb index 3c98b18f99b..f70c69ef588 100644 --- a/spec/lib/banzai/filter/issue_reference_filter_spec.rb +++ b/spec/lib/banzai/filter/issue_reference_filter_spec.rb @@ -343,7 +343,9 @@ describe Banzai::Filter::IssueReferenceFilter do reference = "#{project.full_path}##{issue.iid}" doc = reference_filter("See #{reference}", context) - expect(doc.css('a').first.attr('href')).to eq helper.url_for_issue(issue.iid, project) + link = doc.css('a').first + expect(link.attr('href')).to eq(helper.url_for_issue(issue.iid, project)) + expect(link.text).to include("#{project.full_path}##{issue.iid}") end it 'ignores reference for shorthand cross-reference' do @@ -358,7 +360,9 @@ describe Banzai::Filter::IssueReferenceFilter do doc = reference_filter("See #{reference}", context) - expect(doc.css('a').first.attr('href')).to eq(helper.url_for_issue(issue.iid, project) + "#note_123") + link = doc.css('a').first + expect(link.attr('href')).to eq(helper.url_for_issue(issue.iid, project) + "#note_123") + expect(link.text).to include("#{project.full_path}##{issue.iid}") end it 'links to a valid reference for cross-reference in link href' do @@ -367,7 +371,9 @@ describe Banzai::Filter::IssueReferenceFilter do doc = reference_filter("See #{reference_link}", context) - expect(doc.css('a').first.attr('href')).to eq helper.url_for_issue(issue.iid, project) + "#note_123" + link = doc.css('a').first + expect(link.attr('href')).to eq(helper.url_for_issue(issue.iid, project) + "#note_123") + expect(link.text).to include('Reference') end it 'links to a valid reference for issue reference in the link href' do @@ -375,7 +381,9 @@ describe Banzai::Filter::IssueReferenceFilter do reference_link = %{<a href="#{reference}">Reference</a>} doc = reference_filter("See #{reference_link}", context) - expect(doc.css('a').first.attr('href')).to eq helper.url_for_issue(issue.iid, project) + link = doc.css('a').first + expect(link.attr('href')).to eq(helper.url_for_issue(issue.iid, project)) + expect(link.text).to include('Reference') end end diff --git a/spec/lib/gitlab/auth_spec.rb b/spec/lib/gitlab/auth_spec.rb index 3164d2ebf04..5e822a0026a 100644 --- a/spec/lib/gitlab/auth_spec.rb +++ b/spec/lib/gitlab/auth_spec.rb @@ -251,7 +251,7 @@ describe Gitlab::Auth do end it 'throws an error suggesting user create a PAT when internal auth is disabled' do - allow_any_instance_of(ApplicationSetting).to receive(:password_authentication_enabled?) { false } + allow_any_instance_of(ApplicationSetting).to receive(:password_authentication_enabled_for_git?) { false } expect { gl_auth.find_for_git_client('foo', 'bar', project: nil, ip: 'ip') }.to raise_error(Gitlab::Auth::MissingPersonalAccessTokenError) end @@ -324,6 +324,26 @@ describe Gitlab::Auth do gl_auth.find_with_user_password('ldap_user', 'password') end end + + context "with password authentication disabled for Git" do + before do + stub_application_setting(password_authentication_enabled_for_git: false) + end + + it "does not find user by valid login/password" do + expect(gl_auth.find_with_user_password(username, password)).to be_nil + end + + context "with ldap enabled" do + before do + allow(Gitlab::LDAP::Config).to receive(:enabled?).and_return(true) + end + + it "does not find non-ldap user by valid login/password" do + expect(gl_auth.find_with_user_password(username, password)).to be_nil + end + end + end end private diff --git a/spec/lib/gitlab/encoding_helper_spec.rb b/spec/lib/gitlab/encoding_helper_spec.rb index 9151c66afb3..f6e5c55240f 100644 --- a/spec/lib/gitlab/encoding_helper_spec.rb +++ b/spec/lib/gitlab/encoding_helper_spec.rb @@ -9,6 +9,7 @@ describe Gitlab::EncodingHelper do ["nil", nil, nil], ["empty string", "".encode("ASCII-8BIT"), "".encode("UTF-8")], ["invalid utf-8 encoded string", "my bad string\xE5".force_encoding("UTF-8"), "my bad string"], + ["frozen non-ascii string", "é".force_encoding("ASCII-8BIT").freeze, "é".encode("UTF-8")], [ 'leaves ascii only string as is', 'ascii only string', diff --git a/spec/lib/gitlab/fake_application_settings_spec.rb b/spec/lib/gitlab/fake_application_settings_spec.rb index 34322c2a693..af12e13d36d 100644 --- a/spec/lib/gitlab/fake_application_settings_spec.rb +++ b/spec/lib/gitlab/fake_application_settings_spec.rb @@ -1,25 +1,25 @@ require 'spec_helper' describe Gitlab::FakeApplicationSettings do - let(:defaults) { { password_authentication_enabled: false, foobar: 'asdf', signup_enabled: true, 'test?' => 123 } } + let(:defaults) { { password_authentication_enabled_for_web: false, foobar: 'asdf', signup_enabled: true, 'test?' => 123 } } subject { described_class.new(defaults) } it 'wraps OpenStruct variables properly' do - expect(subject.password_authentication_enabled).to be_falsey + expect(subject.password_authentication_enabled_for_web).to be_falsey expect(subject.signup_enabled).to be_truthy expect(subject.foobar).to eq('asdf') end it 'defines predicate methods' do - expect(subject.password_authentication_enabled?).to be_falsey + expect(subject.password_authentication_enabled_for_web?).to be_falsey expect(subject.signup_enabled?).to be_truthy end it 'predicate method changes when value is updated' do - subject.password_authentication_enabled = true + subject.password_authentication_enabled_for_web = true - expect(subject.password_authentication_enabled?).to be_truthy + expect(subject.password_authentication_enabled_for_web?).to be_truthy end it 'does not define a predicate method' do diff --git a/spec/lib/gitlab/git/repository_spec.rb b/spec/lib/gitlab/git/repository_spec.rb index f0da77c61bb..9da33b94c5e 100644 --- a/spec/lib/gitlab/git/repository_spec.rb +++ b/spec/lib/gitlab/git/repository_spec.rb @@ -1211,12 +1211,21 @@ describe Gitlab::Git::Repository, seed_helper: true do end context 'when no branch names are specified' do - it 'returns all merged branch names' do + before do + repository.create_branch('identical', 'master') + end + + after do + ensure_seeds + end + + it 'returns all merged branch names except for identical one' do names = repository.merged_branch_names expect(names).to include('merge-test') expect(names).to include('fix-mode') expect(names).not_to include('feature') + expect(names).not_to include('identical') end end end diff --git a/spec/lib/gitlab/git/user_spec.rb b/spec/lib/gitlab/git/user_spec.rb index eb8db819045..99d850e1df9 100644 --- a/spec/lib/gitlab/git/user_spec.rb +++ b/spec/lib/gitlab/git/user_spec.rb @@ -1,9 +1,9 @@ require 'spec_helper' describe Gitlab::Git::User do - let(:username) { 'janedo' } - let(:name) { 'Jane Doe' } - let(:email) { 'janedoe@example.com' } + let(:username) { 'janedoe' } + let(:name) { 'Jane Doé' } + let(:email) { 'janedoé@example.com' } let(:gl_id) { 'user-123' } let(:user) do described_class.new(username, name, email, gl_id) @@ -13,7 +13,7 @@ describe Gitlab::Git::User do describe '.from_gitaly' do let(:gitaly_user) do - Gitaly::User.new(gl_username: username, name: name, email: email, gl_id: gl_id) + Gitaly::User.new(gl_username: username, name: name.b, email: email.b, gl_id: gl_id) end subject { described_class.from_gitaly(gitaly_user) } @@ -48,8 +48,13 @@ describe Gitlab::Git::User do it 'creates a Gitaly::User with the correct data' do expect(subject).to be_a(Gitaly::User) expect(subject.gl_username).to eq(username) - expect(subject.name).to eq(name) - expect(subject.email).to eq(email) + + expect(subject.name).to eq(name.b) + expect(subject.name).to be_a_binary_string + + expect(subject.email).to eq(email.b) + expect(subject.email).to be_a_binary_string + expect(subject.gl_id).to eq(gl_id) end end diff --git a/spec/lib/gitlab/import_export/all_models.yml b/spec/lib/gitlab/import_export/all_models.yml index bf1e97654e5..0ecb50f7110 100644 --- a/spec/lib/gitlab/import_export/all_models.yml +++ b/spec/lib/gitlab/import_export/all_models.yml @@ -88,6 +88,7 @@ merge_requests: - metrics - timelogs - head_pipeline +- latest_merge_request_diff merge_request_diff: - merge_request - merge_request_diff_commits diff --git a/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb b/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb index c2bda6f8821..4d78a4b9b13 100644 --- a/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb +++ b/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb @@ -117,6 +117,12 @@ describe Gitlab::ImportExport::ProjectTreeRestorer do expect(st_commits.first[:committed_date]).to be_kind_of(Time) end + it 'has the correct data for merge request latest_merge_request_diff' do + MergeRequest.find_each do |merge_request| + expect(merge_request.latest_merge_request_diff_id).to eq(merge_request.merge_request_diffs.maximum(:id)) + end + end + it 'has labels associated to label links, associated to issues' do expect(Label.first.label_links.first.target).not_to be_nil end diff --git a/spec/lib/gitlab/usage_data_spec.rb b/spec/lib/gitlab/usage_data_spec.rb index a4c1113ae37..b5f2a15ada3 100644 --- a/spec/lib/gitlab/usage_data_spec.rb +++ b/spec/lib/gitlab/usage_data_spec.rb @@ -103,7 +103,7 @@ describe Gitlab::UsageData do subject { described_class.features_usage_data_ce } it 'gathers feature usage data' do - expect(subject[:signup]).to eq(current_application_settings.signup_enabled?) + expect(subject[:signup]).to eq(current_application_settings.allow_signup?) expect(subject[:ldap]).to eq(Gitlab.config.ldap.enabled) expect(subject[:gravatar]).to eq(current_application_settings.gravatar_enabled?) expect(subject[:omniauth]).to eq(Gitlab.config.omniauth.enabled) diff --git a/spec/models/application_setting_spec.rb b/spec/models/application_setting_spec.rb index 47b7150d36f..51bf4e65e5d 100644 --- a/spec/models/application_setting_spec.rb +++ b/spec/models/application_setting_spec.rb @@ -564,4 +564,22 @@ describe ApplicationSetting do expect(setting.key_restriction_for(:foo)).to eq(described_class::FORBIDDEN_KEY_VALUE) end end + + describe '#allow_signup?' do + it 'returns true' do + expect(setting.allow_signup?).to be_truthy + end + + it 'returns false if signup is disabled' do + allow(setting).to receive(:signup_enabled?).and_return(false) + + expect(setting.allow_signup?).to be_falsey + end + + it 'returns false if password authentication is disabled for the web interface' do + allow(setting).to receive(:password_authentication_enabled_for_web?).and_return(false) + + expect(setting.allow_signup?).to be_falsey + end + end end diff --git a/spec/models/concerns/manual_inverse_association_spec.rb b/spec/models/concerns/manual_inverse_association_spec.rb new file mode 100644 index 00000000000..aad40883854 --- /dev/null +++ b/spec/models/concerns/manual_inverse_association_spec.rb @@ -0,0 +1,51 @@ +require 'spec_helper' + +describe ManualInverseAssociation do + let(:model) do + Class.new(MergeRequest) do + belongs_to :manual_association, class_name: 'MergeRequestDiff', foreign_key: :latest_merge_request_diff_id + manual_inverse_association :manual_association, :merge_request + end + end + + before do + stub_const("#{described_class}::Model", model) + end + + let(:instance) { create(:merge_request).becomes(model) } + + describe '.manual_inverse_association' do + context 'when the relation exists' do + before do + instance.create_merge_request_diff + instance.reload + end + + it 'loads the relation' do + expect(instance.manual_association).to be_an_instance_of(MergeRequestDiff) + end + + it 'does not perform extra queries after loading' do + instance.manual_association + + expect { instance.manual_association.merge_request } + .not_to exceed_query_limit(0) + end + + it 'passes arguments to the default association method, to allow reloading' do + query_count = ActiveRecord::QueryRecorder.new do + instance.manual_association + instance.manual_association(true) + end.count + + expect(query_count).to eq(2) + end + end + + context 'when the relation does not return a value' do + it 'does not try to set an inverse' do + expect(instance.manual_association).to be_nil + end + end + end +end diff --git a/spec/models/merge_request_diff_spec.rb b/spec/models/merge_request_diff_spec.rb index 0cfaa17676e..e2a9233a496 100644 --- a/spec/models/merge_request_diff_spec.rb +++ b/spec/models/merge_request_diff_spec.rb @@ -18,8 +18,8 @@ describe MergeRequestDiff do let!(:first_diff) { mr.merge_request_diff } let!(:last_diff) { mr.create_merge_request_diff } - it { expect(last_diff.latest?).to be_truthy } - it { expect(first_diff.latest?).to be_falsey } + it { expect(last_diff.reload).to be_latest } + it { expect(first_diff.reload).not_to be_latest } end describe '#diffs' do @@ -29,7 +29,7 @@ describe MergeRequestDiff do context 'when the :ignore_whitespace_change option is set' do it 'creates a new compare object instead of loading from the DB' do expect(mr_diff).not_to receive(:load_diffs) - expect(Gitlab::Git::Compare).to receive(:new).and_call_original + expect(mr_diff.compare).to receive(:diffs).and_call_original mr_diff.raw_diffs(ignore_whitespace_change: true) end diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb index d250ad50713..3cf8fc816ff 100644 --- a/spec/models/merge_request_spec.rb +++ b/spec/models/merge_request_spec.rb @@ -79,6 +79,43 @@ describe MergeRequest do end end + describe '.set_latest_merge_request_diff_ids!' do + def create_merge_request_with_diffs(source_branch, diffs: 2) + params = { + target_project: project, + target_branch: 'master', + source_project: project, + source_branch: source_branch + } + + create(:merge_request, params).tap do |mr| + diffs.times { mr.merge_request_diffs.create } + end + end + + let(:project) { create(:project) } + + it 'sets IDs for merge requests, whether they are already set or not' do + merge_requests = [ + create_merge_request_with_diffs('feature'), + create_merge_request_with_diffs('feature-conflict'), + create_merge_request_with_diffs('wip', diffs: 0), + create_merge_request_with_diffs('csv') + ] + + merge_requests.take(2).each do |merge_request| + merge_request.update_column(:latest_merge_request_diff_id, nil) + end + + expected = merge_requests.map do |merge_request| + merge_request.merge_request_diffs.maximum(:id) + end + + expect { project.merge_requests.set_latest_merge_request_diff_ids! } + .to change { merge_requests.map { |mr| mr.reload.latest_merge_request_diff_id } }.to(expected) + end + end + describe '#target_branch_sha' do let(:project) { create(:project, :repository) } diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb index e9e6abb0d5f..27f0a99b2fa 100644 --- a/spec/models/repository_spec.rb +++ b/spec/models/repository_spec.rb @@ -299,24 +299,6 @@ describe Repository do it { is_expected.to be_falsey } end - - context 'when pre-loaded merged branches are provided' do - using RSpec::Parameterized::TableSyntax - - where(:branch, :pre_loaded, :expected) do - 'not-merged-branch' | ['branch-merged'] | false - 'branch-merged' | ['not-merged-branch'] | false - 'branch-merged' | ['branch-merged'] | true - 'not-merged-branch' | ['not-merged-branch'] | false - 'master' | ['master'] | false - end - - with_them do - subject { repository.merged_to_root_ref?(branch, pre_loaded) } - - it { is_expected.to eq(expected) } - end - end end describe '#can_be_merged?' do diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 86647ddf6ce..b27c1b2cd1a 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -2143,25 +2143,47 @@ describe User do end end - describe '#allow_password_authentication?' do + describe '#allow_password_authentication_for_web?' do context 'regular user' do let(:user) { build(:user) } - it 'returns true when sign-in is enabled' do - expect(user.allow_password_authentication?).to be_truthy + it 'returns true when password authentication is enabled for the web interface' do + expect(user.allow_password_authentication_for_web?).to be_truthy end - it 'returns false when sign-in is disabled' do - stub_application_setting(password_authentication_enabled: false) + it 'returns false when password authentication is disabled for the web interface' do + stub_application_setting(password_authentication_enabled_for_web: false) - expect(user.allow_password_authentication?).to be_falsey + expect(user.allow_password_authentication_for_web?).to be_falsey end end it 'returns false for ldap user' do user = create(:omniauth_user, provider: 'ldapmain') - expect(user.allow_password_authentication?).to be_falsey + expect(user.allow_password_authentication_for_web?).to be_falsey + end + end + + describe '#allow_password_authentication_for_git?' do + context 'regular user' do + let(:user) { build(:user) } + + it 'returns true when password authentication is enabled for Git' do + expect(user.allow_password_authentication_for_git?).to be_truthy + end + + it 'returns false when password authentication is disabled Git' do + stub_application_setting(password_authentication_enabled_for_git: false) + + expect(user.allow_password_authentication_for_git?).to be_falsey + end + end + + it 'returns false for ldap user' do + user = create(:omniauth_user, provider: 'ldapmain') + + expect(user.allow_password_authentication_for_git?).to be_falsey end end @@ -2381,7 +2403,8 @@ describe User do let(:expected) { !(password_automatically_set || ldap_user || password_authentication_disabled) } before do - stub_application_setting(password_authentication_enabled: !password_authentication_disabled) + stub_application_setting(password_authentication_enabled_for_web: !password_authentication_disabled) + stub_application_setting(password_authentication_enabled_for_git: !password_authentication_disabled) end it 'returns false unless all inputs are true' do diff --git a/spec/requests/api/settings_spec.rb b/spec/requests/api/settings_spec.rb index 5d3e78dd7c8..63175c40a18 100644 --- a/spec/requests/api/settings_spec.rb +++ b/spec/requests/api/settings_spec.rb @@ -10,7 +10,7 @@ describe API::Settings, 'Settings' do expect(response).to have_gitlab_http_status(200) expect(json_response).to be_an Hash expect(json_response['default_projects_limit']).to eq(42) - expect(json_response['password_authentication_enabled']).to be_truthy + expect(json_response['password_authentication_enabled_for_web']).to be_truthy expect(json_response['repository_storages']).to eq(['default']) expect(json_response['koding_enabled']).to be_falsey expect(json_response['koding_url']).to be_nil @@ -37,7 +37,7 @@ describe API::Settings, 'Settings' do it "updates application settings" do put api("/application/settings", admin), default_projects_limit: 3, - password_authentication_enabled: false, + password_authentication_enabled_for_web: false, repository_storages: ['custom'], koding_enabled: true, koding_url: 'http://koding.example.com', @@ -58,7 +58,7 @@ describe API::Settings, 'Settings' do expect(response).to have_gitlab_http_status(200) expect(json_response['default_projects_limit']).to eq(3) - expect(json_response['password_authentication_enabled']).to be_falsey + expect(json_response['password_authentication_enabled_for_web']).to be_falsey expect(json_response['repository_storages']).to eq(['custom']) expect(json_response['koding_enabled']).to be_truthy expect(json_response['koding_url']).to eq('http://koding.example.com') diff --git a/spec/requests/api/v3/settings_spec.rb b/spec/requests/api/v3/settings_spec.rb index 25fa0a8aabd..985bfbfa09c 100644 --- a/spec/requests/api/v3/settings_spec.rb +++ b/spec/requests/api/v3/settings_spec.rb @@ -28,11 +28,11 @@ describe API::V3::Settings, 'Settings' do it "updates application settings" do put v3_api("/application/settings", admin), - default_projects_limit: 3, password_authentication_enabled: false, repository_storage: 'custom', koding_enabled: true, koding_url: 'http://koding.example.com', + default_projects_limit: 3, password_authentication_enabled_for_web: false, repository_storage: 'custom', koding_enabled: true, koding_url: 'http://koding.example.com', plantuml_enabled: true, plantuml_url: 'http://plantuml.example.com' expect(response).to have_gitlab_http_status(200) expect(json_response['default_projects_limit']).to eq(3) - expect(json_response['password_authentication_enabled']).to be_falsey + expect(json_response['password_authentication_enabled_for_web']).to be_falsey expect(json_response['repository_storage']).to eq('custom') expect(json_response['repository_storages']).to eq(['custom']) expect(json_response['koding_enabled']).to be_truthy diff --git a/spec/requests/git_http_spec.rb b/spec/requests/git_http_spec.rb index cd52194033a..a16f98bec36 100644 --- a/spec/requests/git_http_spec.rb +++ b/spec/requests/git_http_spec.rb @@ -463,7 +463,7 @@ describe 'Git HTTP requests' do context 'when internal auth is disabled' do before do - allow_any_instance_of(ApplicationSetting).to receive(:password_authentication_enabled?) { false } + allow_any_instance_of(ApplicationSetting).to receive(:password_authentication_enabled_for_git?) { false } end it 'rejects pulls with personal access token error message' do diff --git a/spec/requests/jwt_controller_spec.rb b/spec/requests/jwt_controller_spec.rb index 94e04ce5608..6f40a02aaa9 100644 --- a/spec/requests/jwt_controller_spec.rb +++ b/spec/requests/jwt_controller_spec.rb @@ -105,7 +105,7 @@ describe JwtController do context 'when internal auth is disabled' do it 'rejects the authorization attempt with personal access token message' do - allow_any_instance_of(ApplicationSetting).to receive(:password_authentication_enabled?) { false } + allow_any_instance_of(ApplicationSetting).to receive(:password_authentication_enabled_for_git?) { false } get '/jwt/auth', parameters, headers expect(response).to have_gitlab_http_status(401) diff --git a/spec/support/matchers/be_a_binary_string.rb b/spec/support/matchers/be_a_binary_string.rb new file mode 100644 index 00000000000..f041ae76167 --- /dev/null +++ b/spec/support/matchers/be_a_binary_string.rb @@ -0,0 +1,9 @@ +RSpec::Matchers.define :be_a_binary_string do |_| + match do |actual| + actual.is_a?(String) && actual.encoding == Encoding.find('ASCII-8BIT') + end + + description do + "be a String with binary encoding" + end +end diff --git a/spec/support/matchers/have_gitlab_http_status.rb b/spec/support/matchers/have_gitlab_http_status.rb index 3198f1b9edd..e7e418cdde4 100644 --- a/spec/support/matchers/have_gitlab_http_status.rb +++ b/spec/support/matchers/have_gitlab_http_status.rb @@ -8,7 +8,11 @@ RSpec::Matchers.define :have_gitlab_http_status do |expected| end failure_message do |actual| + # actual can be either an ActionDispatch::TestResponse (which uses #response_code) + # or a Capybara::Session (which uses #status_code) + response_code = actual.try(:response_code) || actual.try(:status_code) + "expected the response to have status code #{expected.inspect}" \ - " but it was #{actual.response_code}. The response was: #{actual.body}" + " but it was #{response_code}. The response was: #{actual.body}" end end diff --git a/spec/unicorn/unicorn_spec.rb b/spec/unicorn/unicorn_spec.rb index 79a566975df..a4cf479a339 100644 --- a/spec/unicorn/unicorn_spec.rb +++ b/spec/unicorn/unicorn_spec.rb @@ -37,7 +37,22 @@ describe 'Unicorn' do config_path = 'tmp/tests/unicorn.rb' File.write(config_path, config_lines.join("\n") + "\n") - cmd = %W[unicorn -E test -c #{config_path} #{Rails.root.join('config.ru')}] + rackup_path = 'tmp/tests/config.ru' + File.write(rackup_path, <<~EOS) + app = + proc do |env| + if env['REQUEST_METHOD'] == 'GET' + [200, {}, [Process.pid]] + else + Process.kill(env['QUERY_STRING'], Process.pid) + [200, {}, ['Bye!']] + end + end + + run app + EOS + + cmd = %W[unicorn -E test -c #{config_path} #{rackup_path}] @unicorn_master_pid = spawn(*cmd) wait_unicorn_boot!(@unicorn_master_pid, ready_file) WebMock.allow_net_connect! @@ -45,14 +60,14 @@ describe 'Unicorn' do %w[SIGQUIT SIGTERM SIGKILL].each do |signal| it "has a worker that self-terminates on signal #{signal}" do - response = Excon.get('unix:///unicorn_test/pid', socket: @socket_path) + response = Excon.get('unix://', socket: @socket_path) expect(response.status).to eq(200) worker_pid = response.body.to_i expect(worker_pid).to be > 0 begin - Excon.post('unix:///unicorn_test/kill', socket: @socket_path, body: "signal=#{signal}") + Excon.post("unix://?#{signal}", socket: @socket_path) rescue Excon::Error::Socket # The connection may be closed abruptly end diff --git a/spec/workers/pipeline_schedule_worker_spec.rb b/spec/workers/pipeline_schedule_worker_spec.rb index 75197039f5a..e7a4ac0f3d6 100644 --- a/spec/workers/pipeline_schedule_worker_spec.rb +++ b/spec/workers/pipeline_schedule_worker_spec.rb @@ -22,25 +22,32 @@ describe PipelineScheduleWorker do end context 'when there is a scheduled pipeline within next_run_at' do - it 'creates a new pipeline' do - expect { subject }.to change { project.pipelines.count }.by(1) - expect(Ci::Pipeline.last).to be_schedule + shared_examples 'successful scheduling' do + it 'creates a new pipeline' do + expect { subject }.to change { project.pipelines.count }.by(1) + expect(Ci::Pipeline.last).to be_schedule + + pipeline_schedule.reload + expect(pipeline_schedule.next_run_at).to be > Time.now + expect(pipeline_schedule).to eq(project.pipelines.last.pipeline_schedule) + expect(pipeline_schedule).to be_active + end end - it 'updates the next_run_at field' do - subject + it_behaves_like 'successful scheduling' - expect(pipeline_schedule.reload.next_run_at).to be > Time.now - end - - it 'sets the schedule on the pipeline' do - subject + context 'when the latest commit contains [ci skip]' do + before do + allow_any_instance_of(Ci::Pipeline) + .to receive(:git_commit_message) + .and_return('some commit [ci skip]') + end - expect(project.pipelines.last.pipeline_schedule).to eq(pipeline_schedule) + it_behaves_like 'successful scheduling' end end - context 'inactive schedule' do + context 'when the schedule is deactivated' do before do pipeline_schedule.deactivate! end diff --git a/yarn.lock b/yarn.lock index 9bdf5e0f64b..600e8e75ef6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,6 +2,58 @@ # yarn lockfile v1 +"@babel/code-frame@7.0.0-beta.32", "@babel/code-frame@^7.0.0-beta.31": + version "7.0.0-beta.32" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.0.0-beta.32.tgz#04f231b8ec70370df830d9926ce0f5add074ec4c" + dependencies: + chalk "^2.0.0" + esutils "^2.0.2" + js-tokens "^3.0.0" + +"@babel/helper-function-name@7.0.0-beta.32": + version "7.0.0-beta.32" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.0.0-beta.32.tgz#6161af4419f1b4e3ed2d28c0c79c160e218be1f3" + dependencies: + "@babel/helper-get-function-arity" "7.0.0-beta.32" + "@babel/template" "7.0.0-beta.32" + "@babel/types" "7.0.0-beta.32" + +"@babel/helper-get-function-arity@7.0.0-beta.32": + version "7.0.0-beta.32" + resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0-beta.32.tgz#93721a99db3757de575a83bab7c453299abca568" + dependencies: + "@babel/types" "7.0.0-beta.32" + +"@babel/template@7.0.0-beta.32": + version "7.0.0-beta.32" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.0.0-beta.32.tgz#e1d9fdbd2a7bcf128f2f920744a67dab18072495" + dependencies: + "@babel/code-frame" "7.0.0-beta.32" + "@babel/types" "7.0.0-beta.32" + babylon "7.0.0-beta.32" + lodash "^4.2.0" + +"@babel/traverse@^7.0.0-beta.31": + version "7.0.0-beta.32" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.0.0-beta.32.tgz#b78b754c6e1af3360626183738e4c7a05951bc99" + dependencies: + "@babel/code-frame" "7.0.0-beta.32" + "@babel/helper-function-name" "7.0.0-beta.32" + "@babel/types" "7.0.0-beta.32" + babylon "7.0.0-beta.32" + debug "^3.0.1" + globals "^10.0.0" + invariant "^2.2.0" + lodash "^4.2.0" + +"@babel/types@7.0.0-beta.32", "@babel/types@^7.0.0-beta.31": + version "7.0.0-beta.32" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.0.0-beta.32.tgz#c317d0ecc89297b80bbcb2f50608e31f6452a5ff" + dependencies: + esutils "^2.0.2" + lodash "^4.2.0" + to-fast-properties "^2.0.0" + "@gitlab-org/gitlab-svgs@^1.0.2": version "1.0.2" resolved "https://registry.yarnpkg.com/@gitlab-org/gitlab-svgs/-/gitlab-svgs-1.0.2.tgz#e4d29058e2bb438ba71ac525c6397ef15ae2877b" @@ -105,6 +157,12 @@ ansi-styles@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" +ansi-styles@^3.1.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.0.tgz#c159b8d5be0f9e5a6f346dab94f16ce022161b88" + dependencies: + color-convert "^1.9.0" + anymatch@^1.3.0: version "1.3.2" resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-1.3.2.tgz#553dcb8f91e3c889845dfdba34c77721b90b9d7a" @@ -270,11 +328,11 @@ axios-mock-adapter@^1.10.0: dependencies: deep-equal "^1.0.1" -axios@^0.16.2: - version "0.16.2" - resolved "https://registry.yarnpkg.com/axios/-/axios-0.16.2.tgz#ba4f92f17167dfbab40983785454b9ac149c3c6d" +axios@^0.17.1: + version "0.17.1" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.17.1.tgz#2d8e3e5d0bdbd7327f91bc814f5c57660f81824d" dependencies: - follow-redirects "^1.2.3" + follow-redirects "^1.2.5" is-buffer "^1.1.5" babel-code-frame@^6.11.0, babel-code-frame@^6.22.0: @@ -285,7 +343,7 @@ babel-code-frame@^6.11.0, babel-code-frame@^6.22.0: esutils "^2.0.2" js-tokens "^3.0.0" -babel-code-frame@^6.16.0: +babel-code-frame@^6.16.0, babel-code-frame@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" dependencies: @@ -293,40 +351,40 @@ babel-code-frame@^6.16.0: esutils "^2.0.2" js-tokens "^3.0.2" -babel-core@^6.22.1, babel-core@^6.23.0: - version "6.23.1" - resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.23.1.tgz#c143cb621bb2f621710c220c5d579d15b8a442df" +babel-core@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.26.0.tgz#af32f78b31a6fcef119c87b0fd8d9753f03a0bb8" dependencies: - babel-code-frame "^6.22.0" - babel-generator "^6.23.0" - babel-helpers "^6.23.0" + babel-code-frame "^6.26.0" + babel-generator "^6.26.0" + babel-helpers "^6.24.1" babel-messages "^6.23.0" - babel-register "^6.23.0" - babel-runtime "^6.22.0" - babel-template "^6.23.0" - babel-traverse "^6.23.1" - babel-types "^6.23.0" - babylon "^6.11.0" - convert-source-map "^1.1.0" - debug "^2.1.1" - json5 "^0.5.0" - lodash "^4.2.0" - minimatch "^3.0.2" - path-is-absolute "^1.0.0" - private "^0.1.6" + babel-register "^6.26.0" + babel-runtime "^6.26.0" + babel-template "^6.26.0" + babel-traverse "^6.26.0" + babel-types "^6.26.0" + babylon "^6.18.0" + convert-source-map "^1.5.0" + debug "^2.6.8" + json5 "^0.5.1" + lodash "^4.17.4" + minimatch "^3.0.4" + path-is-absolute "^1.0.1" + private "^0.1.7" slash "^1.0.0" - source-map "^0.5.0" + source-map "^0.5.6" -babel-eslint@^7.2.1: - version "7.2.1" - resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-7.2.1.tgz#079422eb73ba811e3ca0865ce87af29327f8c52f" +babel-eslint@^8.0.2: + version "8.0.2" + resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-8.0.2.tgz#e44fb9a037d749486071d52d65312f5c20aa7530" dependencies: - babel-code-frame "^6.22.0" - babel-traverse "^6.23.1" - babel-types "^6.23.0" - babylon "^6.16.1" + "@babel/code-frame" "^7.0.0-beta.31" + "@babel/traverse" "^7.0.0-beta.31" + "@babel/types" "^7.0.0-beta.31" + babylon "^7.0.0-beta.31" -babel-generator@^6.18.0, babel-generator@^6.23.0: +babel-generator@^6.18.0: version "6.23.0" resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.23.0.tgz#6b8edab956ef3116f79d8c84c5a3c05f32a74bc5" dependencies: @@ -339,127 +397,140 @@ babel-generator@^6.18.0, babel-generator@^6.23.0: source-map "^0.5.0" trim-right "^1.0.1" -babel-helper-bindify-decorators@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-helper-bindify-decorators/-/babel-helper-bindify-decorators-6.22.0.tgz#d7f5bc261275941ac62acfc4e20dacfb8a3fe952" +babel-generator@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.26.0.tgz#ac1ae20070b79f6e3ca1d3269613053774f20dc5" dependencies: - babel-runtime "^6.22.0" - babel-traverse "^6.22.0" - babel-types "^6.22.0" + babel-messages "^6.23.0" + babel-runtime "^6.26.0" + babel-types "^6.26.0" + detect-indent "^4.0.0" + jsesc "^1.3.0" + lodash "^4.17.4" + source-map "^0.5.6" + trim-right "^1.0.1" -babel-helper-builder-binary-assignment-operator-visitor@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.22.0.tgz#29df56be144d81bdeac08262bfa41d2c5e91cdcd" +babel-helper-bindify-decorators@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-bindify-decorators/-/babel-helper-bindify-decorators-6.24.1.tgz#14c19e5f142d7b47f19a52431e52b1ccbc40a330" dependencies: - babel-helper-explode-assignable-expression "^6.22.0" babel-runtime "^6.22.0" - babel-types "^6.22.0" + babel-traverse "^6.24.1" + babel-types "^6.24.1" -babel-helper-call-delegate@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-helper-call-delegate/-/babel-helper-call-delegate-6.22.0.tgz#119921b56120f17e9dae3f74b4f5cc7bcc1b37ef" +babel-helper-builder-binary-assignment-operator-visitor@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz#cce4517ada356f4220bcae8a02c2b346f9a56664" dependencies: - babel-helper-hoist-variables "^6.22.0" + babel-helper-explode-assignable-expression "^6.24.1" babel-runtime "^6.22.0" - babel-traverse "^6.22.0" - babel-types "^6.22.0" + babel-types "^6.24.1" -babel-helper-define-map@^6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-helper-define-map/-/babel-helper-define-map-6.23.0.tgz#1444f960c9691d69a2ced6a205315f8fd00804e7" +babel-helper-call-delegate@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz#ece6aacddc76e41c3461f88bfc575bd0daa2df8d" dependencies: - babel-helper-function-name "^6.23.0" + babel-helper-hoist-variables "^6.24.1" babel-runtime "^6.22.0" - babel-types "^6.23.0" - lodash "^4.2.0" + babel-traverse "^6.24.1" + babel-types "^6.24.1" -babel-helper-explode-assignable-expression@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.22.0.tgz#c97bf76eed3e0bae4048121f2b9dae1a4e7d0478" +babel-helper-define-map@^6.24.1: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz#a5f56dab41a25f97ecb498c7ebaca9819f95be5f" dependencies: - babel-runtime "^6.22.0" - babel-traverse "^6.22.0" - babel-types "^6.22.0" + babel-helper-function-name "^6.24.1" + babel-runtime "^6.26.0" + babel-types "^6.26.0" + lodash "^4.17.4" -babel-helper-explode-class@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-helper-explode-class/-/babel-helper-explode-class-6.22.0.tgz#646304924aa6388a516843ba7f1855ef8dfeb69b" +babel-helper-explode-assignable-expression@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz#f25b82cf7dc10433c55f70592d5746400ac22caa" dependencies: - babel-helper-bindify-decorators "^6.22.0" babel-runtime "^6.22.0" - babel-traverse "^6.22.0" - babel-types "^6.22.0" + babel-traverse "^6.24.1" + babel-types "^6.24.1" -babel-helper-function-name@^6.22.0, babel-helper-function-name@^6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-helper-function-name/-/babel-helper-function-name-6.23.0.tgz#25742d67175c8903dbe4b6cb9d9e1fcb8dcf23a6" +babel-helper-explode-class@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-explode-class/-/babel-helper-explode-class-6.24.1.tgz#7dc2a3910dee007056e1e31d640ced3d54eaa9eb" dependencies: - babel-helper-get-function-arity "^6.22.0" + babel-helper-bindify-decorators "^6.24.1" babel-runtime "^6.22.0" - babel-template "^6.23.0" - babel-traverse "^6.23.0" - babel-types "^6.23.0" + babel-traverse "^6.24.1" + babel-types "^6.24.1" -babel-helper-get-function-arity@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.22.0.tgz#0beb464ad69dc7347410ac6ade9f03a50634f5ce" +babel-helper-function-name@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz#d3475b8c03ed98242a25b48351ab18399d3580a9" dependencies: + babel-helper-get-function-arity "^6.24.1" babel-runtime "^6.22.0" - babel-types "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" -babel-helper-hoist-variables@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.22.0.tgz#3eacbf731d80705845dd2e9718f600cfb9b4ba72" +babel-helper-get-function-arity@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz#8f7782aa93407c41d3aa50908f89b031b1b6853d" dependencies: babel-runtime "^6.22.0" - babel-types "^6.22.0" + babel-types "^6.24.1" -babel-helper-optimise-call-expression@^6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.23.0.tgz#f3ee7eed355b4282138b33d02b78369e470622f5" +babel-helper-hoist-variables@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz#1ecb27689c9d25513eadbc9914a73f5408be7a76" dependencies: babel-runtime "^6.22.0" - babel-types "^6.23.0" + babel-types "^6.24.1" -babel-helper-regex@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-helper-regex/-/babel-helper-regex-6.22.0.tgz#79f532be1647b1f0ee3474b5f5c3da58001d247d" +babel-helper-optimise-call-expression@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz#f7a13427ba9f73f8f4fa993c54a97882d1244257" dependencies: babel-runtime "^6.22.0" - babel-types "^6.22.0" - lodash "^4.2.0" + babel-types "^6.24.1" -babel-helper-remap-async-to-generator@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.22.0.tgz#2186ae73278ed03b8b15ced089609da981053383" +babel-helper-regex@^6.24.1: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz#325c59f902f82f24b74faceed0363954f6495e72" + dependencies: + babel-runtime "^6.26.0" + babel-types "^6.26.0" + lodash "^4.17.4" + +babel-helper-remap-async-to-generator@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz#5ec581827ad723fecdd381f1c928390676e4551b" dependencies: - babel-helper-function-name "^6.22.0" + babel-helper-function-name "^6.24.1" babel-runtime "^6.22.0" - babel-template "^6.22.0" - babel-traverse "^6.22.0" - babel-types "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" -babel-helper-replace-supers@^6.22.0, babel-helper-replace-supers@^6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-helper-replace-supers/-/babel-helper-replace-supers-6.23.0.tgz#eeaf8ad9b58ec4337ca94223bacdca1f8d9b4bfd" +babel-helper-replace-supers@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz#bf6dbfe43938d17369a213ca8a8bf74b6a90ab1a" dependencies: - babel-helper-optimise-call-expression "^6.23.0" + babel-helper-optimise-call-expression "^6.24.1" babel-messages "^6.23.0" babel-runtime "^6.22.0" - babel-template "^6.23.0" - babel-traverse "^6.23.0" - babel-types "^6.23.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" -babel-helpers@^6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-helpers/-/babel-helpers-6.23.0.tgz#4f8f2e092d0b6a8808a4bde79c27f1e2ecf0d992" +babel-helpers@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helpers/-/babel-helpers-6.24.1.tgz#3471de9caec388e5c850e597e58a26ddf37602b2" dependencies: babel-runtime "^6.22.0" - babel-template "^6.23.0" + babel-template "^6.24.1" -babel-loader@^7.1.1: - version "7.1.1" - resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-7.1.1.tgz#b87134c8b12e3e4c2a94e0546085bc680a2b8488" +babel-loader@^7.1.2: + version "7.1.2" + resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-7.1.2.tgz#f6cbe122710f1aa2af4d881c6d5b54358ca24126" dependencies: find-cache-dir "^1.0.0" loader-utils "^1.0.2" @@ -477,13 +548,13 @@ babel-plugin-check-es2015-constants@^6.22.0: dependencies: babel-runtime "^6.22.0" -babel-plugin-istanbul@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-4.0.0.tgz#36bde8fbef4837e5ff0366531a2beabd7b1ffa10" +babel-plugin-istanbul@^4.1.5: + version "4.1.5" + resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-4.1.5.tgz#6760cdd977f411d3e175bb064f2bc327d99b2b6e" dependencies: find-up "^2.1.0" - istanbul-lib-instrument "^1.4.2" - test-exclude "^4.0.0" + istanbul-lib-instrument "^1.7.5" + test-exclude "^4.1.1" babel-plugin-syntax-async-functions@^6.8.0: version "6.13.0" @@ -517,46 +588,46 @@ babel-plugin-syntax-trailing-function-commas@^6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz#ba0360937f8d06e40180a43fe0d5616fff532cf3" -babel-plugin-transform-async-generator-functions@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-generator-functions/-/babel-plugin-transform-async-generator-functions-6.22.0.tgz#a720a98153a7596f204099cd5409f4b3c05bab46" +babel-plugin-transform-async-generator-functions@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-generator-functions/-/babel-plugin-transform-async-generator-functions-6.24.1.tgz#f058900145fd3e9907a6ddf28da59f215258a5db" dependencies: - babel-helper-remap-async-to-generator "^6.22.0" + babel-helper-remap-async-to-generator "^6.24.1" babel-plugin-syntax-async-generators "^6.5.0" babel-runtime "^6.22.0" -babel-plugin-transform-async-to-generator@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.22.0.tgz#194b6938ec195ad36efc4c33a971acf00d8cd35e" +babel-plugin-transform-async-to-generator@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz#6536e378aff6cb1d5517ac0e40eb3e9fc8d08761" dependencies: - babel-helper-remap-async-to-generator "^6.22.0" + babel-helper-remap-async-to-generator "^6.24.1" babel-plugin-syntax-async-functions "^6.8.0" babel-runtime "^6.22.0" -babel-plugin-transform-class-properties@^6.22.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.23.0.tgz#187b747ee404399013563c993db038f34754ac3b" +babel-plugin-transform-class-properties@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz#6a79763ea61d33d36f37b611aa9def81a81b46ac" dependencies: - babel-helper-function-name "^6.23.0" + babel-helper-function-name "^6.24.1" babel-plugin-syntax-class-properties "^6.8.0" babel-runtime "^6.22.0" - babel-template "^6.23.0" + babel-template "^6.24.1" -babel-plugin-transform-decorators@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-decorators/-/babel-plugin-transform-decorators-6.22.0.tgz#c03635b27a23b23b7224f49232c237a73988d27c" +babel-plugin-transform-decorators@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-decorators/-/babel-plugin-transform-decorators-6.24.1.tgz#788013d8f8c6b5222bdf7b344390dfd77569e24d" dependencies: - babel-helper-explode-class "^6.22.0" + babel-helper-explode-class "^6.24.1" babel-plugin-syntax-decorators "^6.13.0" babel-runtime "^6.22.0" - babel-template "^6.22.0" - babel-types "^6.22.0" + babel-template "^6.24.1" + babel-types "^6.24.1" -babel-plugin-transform-define@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-define/-/babel-plugin-transform-define-1.2.0.tgz#f036bda05162f29a542e434f585da1ccf1e7ec6a" +babel-plugin-transform-define@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-define/-/babel-plugin-transform-define-1.3.0.tgz#94c5f9459c810c738cc7c50cbd44a31829d6f319" dependencies: - lodash.get "4.4.2" + lodash "4.17.4" traverse "0.6.6" babel-plugin-transform-es2015-arrow-functions@^6.22.0: @@ -571,36 +642,36 @@ babel-plugin-transform-es2015-block-scoped-functions@^6.22.0: dependencies: babel-runtime "^6.22.0" -babel-plugin-transform-es2015-block-scoping@^6.22.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.23.0.tgz#e48895cf0b375be148cd7c8879b422707a053b51" +babel-plugin-transform-es2015-block-scoping@^6.24.1: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz#d70f5299c1308d05c12f463813b0a09e73b1895f" dependencies: - babel-runtime "^6.22.0" - babel-template "^6.23.0" - babel-traverse "^6.23.0" - babel-types "^6.23.0" - lodash "^4.2.0" + babel-runtime "^6.26.0" + babel-template "^6.26.0" + babel-traverse "^6.26.0" + babel-types "^6.26.0" + lodash "^4.17.4" -babel-plugin-transform-es2015-classes@^6.22.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.23.0.tgz#49b53f326202a2fd1b3bbaa5e2edd8a4f78643c1" +babel-plugin-transform-es2015-classes@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz#5a4c58a50c9c9461e564b4b2a3bfabc97a2584db" dependencies: - babel-helper-define-map "^6.23.0" - babel-helper-function-name "^6.23.0" - babel-helper-optimise-call-expression "^6.23.0" - babel-helper-replace-supers "^6.23.0" + babel-helper-define-map "^6.24.1" + babel-helper-function-name "^6.24.1" + babel-helper-optimise-call-expression "^6.24.1" + babel-helper-replace-supers "^6.24.1" babel-messages "^6.23.0" babel-runtime "^6.22.0" - babel-template "^6.23.0" - babel-traverse "^6.23.0" - babel-types "^6.23.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" -babel-plugin-transform-es2015-computed-properties@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.22.0.tgz#7c383e9629bba4820c11b0425bdd6290f7f057e7" +babel-plugin-transform-es2015-computed-properties@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz#6fe2a8d16895d5634f4cd999b6d3480a308159b3" dependencies: babel-runtime "^6.22.0" - babel-template "^6.22.0" + babel-template "^6.24.1" babel-plugin-transform-es2015-destructuring@^6.22.0: version "6.23.0" @@ -608,12 +679,12 @@ babel-plugin-transform-es2015-destructuring@^6.22.0: dependencies: babel-runtime "^6.22.0" -babel-plugin-transform-es2015-duplicate-keys@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.22.0.tgz#672397031c21610d72dd2bbb0ba9fb6277e1c36b" +babel-plugin-transform-es2015-duplicate-keys@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz#73eb3d310ca969e3ef9ec91c53741a6f1576423e" dependencies: babel-runtime "^6.22.0" - babel-types "^6.22.0" + babel-types "^6.24.1" babel-plugin-transform-es2015-for-of@^6.22.0: version "6.23.0" @@ -621,13 +692,13 @@ babel-plugin-transform-es2015-for-of@^6.22.0: dependencies: babel-runtime "^6.22.0" -babel-plugin-transform-es2015-function-name@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.22.0.tgz#f5fcc8b09093f9a23c76ac3d9e392c3ec4b77104" +babel-plugin-transform-es2015-function-name@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz#834c89853bc36b1af0f3a4c5dbaa94fd8eacaa8b" dependencies: - babel-helper-function-name "^6.22.0" + babel-helper-function-name "^6.24.1" babel-runtime "^6.22.0" - babel-types "^6.22.0" + babel-types "^6.24.1" babel-plugin-transform-es2015-literals@^6.22.0: version "6.22.0" @@ -635,63 +706,63 @@ babel-plugin-transform-es2015-literals@^6.22.0: dependencies: babel-runtime "^6.22.0" -babel-plugin-transform-es2015-modules-amd@^6.24.0: - version "6.24.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.0.tgz#a1911fb9b7ec7e05a43a63c5995007557bcf6a2e" +babel-plugin-transform-es2015-modules-amd@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz#3b3e54017239842d6d19c3011c4bd2f00a00d154" dependencies: - babel-plugin-transform-es2015-modules-commonjs "^6.24.0" + babel-plugin-transform-es2015-modules-commonjs "^6.24.1" babel-runtime "^6.22.0" - babel-template "^6.22.0" + babel-template "^6.24.1" -babel-plugin-transform-es2015-modules-commonjs@^6.24.0: - version "6.24.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.24.0.tgz#e921aefb72c2cc26cb03d107626156413222134f" +babel-plugin-transform-es2015-modules-commonjs@^6.24.1: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.0.tgz#0d8394029b7dc6abe1a97ef181e00758dd2e5d8a" dependencies: - babel-plugin-transform-strict-mode "^6.22.0" - babel-runtime "^6.22.0" - babel-template "^6.23.0" - babel-types "^6.23.0" + babel-plugin-transform-strict-mode "^6.24.1" + babel-runtime "^6.26.0" + babel-template "^6.26.0" + babel-types "^6.26.0" -babel-plugin-transform-es2015-modules-systemjs@^6.22.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.23.0.tgz#ae3469227ffac39b0310d90fec73bfdc4f6317b0" +babel-plugin-transform-es2015-modules-systemjs@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz#ff89a142b9119a906195f5f106ecf305d9407d23" dependencies: - babel-helper-hoist-variables "^6.22.0" + babel-helper-hoist-variables "^6.24.1" babel-runtime "^6.22.0" - babel-template "^6.23.0" + babel-template "^6.24.1" -babel-plugin-transform-es2015-modules-umd@^6.24.0: - version "6.24.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.0.tgz#fd5fa63521cae8d273927c3958afd7c067733450" +babel-plugin-transform-es2015-modules-umd@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz#ac997e6285cd18ed6176adb607d602344ad38468" dependencies: - babel-plugin-transform-es2015-modules-amd "^6.24.0" + babel-plugin-transform-es2015-modules-amd "^6.24.1" babel-runtime "^6.22.0" - babel-template "^6.23.0" + babel-template "^6.24.1" -babel-plugin-transform-es2015-object-super@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.22.0.tgz#daa60e114a042ea769dd53fe528fc82311eb98fc" +babel-plugin-transform-es2015-object-super@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz#24cef69ae21cb83a7f8603dad021f572eb278f8d" dependencies: - babel-helper-replace-supers "^6.22.0" + babel-helper-replace-supers "^6.24.1" babel-runtime "^6.22.0" -babel-plugin-transform-es2015-parameters@^6.22.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.23.0.tgz#3a2aabb70c8af945d5ce386f1a4250625a83ae3b" +babel-plugin-transform-es2015-parameters@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz#57ac351ab49caf14a97cd13b09f66fdf0a625f2b" dependencies: - babel-helper-call-delegate "^6.22.0" - babel-helper-get-function-arity "^6.22.0" + babel-helper-call-delegate "^6.24.1" + babel-helper-get-function-arity "^6.24.1" babel-runtime "^6.22.0" - babel-template "^6.23.0" - babel-traverse "^6.23.0" - babel-types "^6.23.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" -babel-plugin-transform-es2015-shorthand-properties@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.22.0.tgz#8ba776e0affaa60bff21e921403b8a652a2ff723" +babel-plugin-transform-es2015-shorthand-properties@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz#24f875d6721c87661bbd99a4622e51f14de38aa0" dependencies: babel-runtime "^6.22.0" - babel-types "^6.22.0" + babel-types "^6.24.1" babel-plugin-transform-es2015-spread@^6.22.0: version "6.22.0" @@ -699,13 +770,13 @@ babel-plugin-transform-es2015-spread@^6.22.0: dependencies: babel-runtime "^6.22.0" -babel-plugin-transform-es2015-sticky-regex@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.22.0.tgz#ab316829e866ee3f4b9eb96939757d19a5bc4593" +babel-plugin-transform-es2015-sticky-regex@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz#00c1cdb1aca71112cdf0cf6126c2ed6b457ccdbc" dependencies: - babel-helper-regex "^6.22.0" + babel-helper-regex "^6.24.1" babel-runtime "^6.22.0" - babel-types "^6.22.0" + babel-types "^6.24.1" babel-plugin-transform-es2015-template-literals@^6.22.0: version "6.22.0" @@ -719,19 +790,19 @@ babel-plugin-transform-es2015-typeof-symbol@^6.22.0: dependencies: babel-runtime "^6.22.0" -babel-plugin-transform-es2015-unicode-regex@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.22.0.tgz#8d9cc27e7ee1decfe65454fb986452a04a613d20" +babel-plugin-transform-es2015-unicode-regex@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz#d38b12f42ea7323f729387f18a7c5ae1faeb35e9" dependencies: - babel-helper-regex "^6.22.0" + babel-helper-regex "^6.24.1" babel-runtime "^6.22.0" regexpu-core "^2.0.0" -babel-plugin-transform-exponentiation-operator@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.22.0.tgz#d57c8335281918e54ef053118ce6eb108468084d" +babel-plugin-transform-exponentiation-operator@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz#2ab0c9c7f3098fa48907772bb813fe41e8de3a0e" dependencies: - babel-helper-builder-binary-assignment-operator-visitor "^6.22.0" + babel-helper-builder-binary-assignment-operator-visitor "^6.24.1" babel-plugin-syntax-exponentiation-operator "^6.8.0" babel-runtime "^6.22.0" @@ -742,99 +813,99 @@ babel-plugin-transform-object-rest-spread@^6.22.0: babel-plugin-syntax-object-rest-spread "^6.8.0" babel-runtime "^6.22.0" -babel-plugin-transform-regenerator@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.22.0.tgz#65740593a319c44522157538d690b84094617ea6" +babel-plugin-transform-regenerator@^6.24.1: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz#e0703696fbde27f0a3efcacf8b4dca2f7b3a8f2f" dependencies: - regenerator-transform "0.9.8" + regenerator-transform "^0.10.0" -babel-plugin-transform-strict-mode@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.22.0.tgz#e008df01340fdc87e959da65991b7e05970c8c7c" +babel-plugin-transform-strict-mode@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz#d5faf7aa578a65bbe591cf5edae04a0c67020758" dependencies: babel-runtime "^6.22.0" - babel-types "^6.22.0" + babel-types "^6.24.1" -babel-preset-es2015@^6.24.0: - version "6.24.0" - resolved "https://registry.yarnpkg.com/babel-preset-es2015/-/babel-preset-es2015-6.24.0.tgz#c162d68b1932696e036cd3110dc1ccd303d2673a" +babel-preset-es2015@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-preset-es2015/-/babel-preset-es2015-6.24.1.tgz#d44050d6bc2c9feea702aaf38d727a0210538939" dependencies: babel-plugin-check-es2015-constants "^6.22.0" babel-plugin-transform-es2015-arrow-functions "^6.22.0" babel-plugin-transform-es2015-block-scoped-functions "^6.22.0" - babel-plugin-transform-es2015-block-scoping "^6.22.0" - babel-plugin-transform-es2015-classes "^6.22.0" - babel-plugin-transform-es2015-computed-properties "^6.22.0" + babel-plugin-transform-es2015-block-scoping "^6.24.1" + babel-plugin-transform-es2015-classes "^6.24.1" + babel-plugin-transform-es2015-computed-properties "^6.24.1" babel-plugin-transform-es2015-destructuring "^6.22.0" - babel-plugin-transform-es2015-duplicate-keys "^6.22.0" + babel-plugin-transform-es2015-duplicate-keys "^6.24.1" babel-plugin-transform-es2015-for-of "^6.22.0" - babel-plugin-transform-es2015-function-name "^6.22.0" + babel-plugin-transform-es2015-function-name "^6.24.1" babel-plugin-transform-es2015-literals "^6.22.0" - babel-plugin-transform-es2015-modules-amd "^6.24.0" - babel-plugin-transform-es2015-modules-commonjs "^6.24.0" - babel-plugin-transform-es2015-modules-systemjs "^6.22.0" - babel-plugin-transform-es2015-modules-umd "^6.24.0" - babel-plugin-transform-es2015-object-super "^6.22.0" - babel-plugin-transform-es2015-parameters "^6.22.0" - babel-plugin-transform-es2015-shorthand-properties "^6.22.0" + babel-plugin-transform-es2015-modules-amd "^6.24.1" + babel-plugin-transform-es2015-modules-commonjs "^6.24.1" + babel-plugin-transform-es2015-modules-systemjs "^6.24.1" + babel-plugin-transform-es2015-modules-umd "^6.24.1" + babel-plugin-transform-es2015-object-super "^6.24.1" + babel-plugin-transform-es2015-parameters "^6.24.1" + babel-plugin-transform-es2015-shorthand-properties "^6.24.1" babel-plugin-transform-es2015-spread "^6.22.0" - babel-plugin-transform-es2015-sticky-regex "^6.22.0" + babel-plugin-transform-es2015-sticky-regex "^6.24.1" babel-plugin-transform-es2015-template-literals "^6.22.0" babel-plugin-transform-es2015-typeof-symbol "^6.22.0" - babel-plugin-transform-es2015-unicode-regex "^6.22.0" - babel-plugin-transform-regenerator "^6.22.0" + babel-plugin-transform-es2015-unicode-regex "^6.24.1" + babel-plugin-transform-regenerator "^6.24.1" -babel-preset-es2016@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-preset-es2016/-/babel-preset-es2016-6.22.0.tgz#b061aaa3983d40c9fbacfa3743b5df37f336156c" +babel-preset-es2016@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-preset-es2016/-/babel-preset-es2016-6.24.1.tgz#f900bf93e2ebc0d276df9b8ab59724ebfd959f8b" dependencies: - babel-plugin-transform-exponentiation-operator "^6.22.0" + babel-plugin-transform-exponentiation-operator "^6.24.1" -babel-preset-es2017@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-preset-es2017/-/babel-preset-es2017-6.22.0.tgz#de2f9da5a30c50d293fb54a0ba15d6ddc573f0f2" +babel-preset-es2017@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-preset-es2017/-/babel-preset-es2017-6.24.1.tgz#597beadfb9f7f208bcfd8a12e9b2b29b8b2f14d1" dependencies: babel-plugin-syntax-trailing-function-commas "^6.22.0" - babel-plugin-transform-async-to-generator "^6.22.0" + babel-plugin-transform-async-to-generator "^6.24.1" -babel-preset-latest@^6.24.0: - version "6.24.0" - resolved "https://registry.yarnpkg.com/babel-preset-latest/-/babel-preset-latest-6.24.0.tgz#a68d20f509edcc5d7433a48dfaebf7e4f2cd4cb7" +babel-preset-latest@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-preset-latest/-/babel-preset-latest-6.24.1.tgz#677de069154a7485c2d25c577c02f624b85b85e8" dependencies: - babel-preset-es2015 "^6.24.0" - babel-preset-es2016 "^6.22.0" - babel-preset-es2017 "^6.22.0" + babel-preset-es2015 "^6.24.1" + babel-preset-es2016 "^6.24.1" + babel-preset-es2017 "^6.24.1" -babel-preset-stage-2@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-preset-stage-2/-/babel-preset-stage-2-6.22.0.tgz#ccd565f19c245cade394b21216df704a73b27c07" +babel-preset-stage-2@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-preset-stage-2/-/babel-preset-stage-2-6.24.1.tgz#d9e2960fb3d71187f0e64eec62bc07767219bdc1" dependencies: babel-plugin-syntax-dynamic-import "^6.18.0" - babel-plugin-transform-class-properties "^6.22.0" - babel-plugin-transform-decorators "^6.22.0" - babel-preset-stage-3 "^6.22.0" + babel-plugin-transform-class-properties "^6.24.1" + babel-plugin-transform-decorators "^6.24.1" + babel-preset-stage-3 "^6.24.1" -babel-preset-stage-3@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-preset-stage-3/-/babel-preset-stage-3-6.22.0.tgz#a4e92bbace7456fafdf651d7a7657ee0bbca9c2e" +babel-preset-stage-3@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-preset-stage-3/-/babel-preset-stage-3-6.24.1.tgz#836ada0a9e7a7fa37cb138fb9326f87934a48395" dependencies: babel-plugin-syntax-trailing-function-commas "^6.22.0" - babel-plugin-transform-async-generator-functions "^6.22.0" - babel-plugin-transform-async-to-generator "^6.22.0" - babel-plugin-transform-exponentiation-operator "^6.22.0" + babel-plugin-transform-async-generator-functions "^6.24.1" + babel-plugin-transform-async-to-generator "^6.24.1" + babel-plugin-transform-exponentiation-operator "^6.24.1" babel-plugin-transform-object-rest-spread "^6.22.0" -babel-register@^6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.23.0.tgz#c9aa3d4cca94b51da34826c4a0f9e08145d74ff3" +babel-register@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.26.0.tgz#6ed021173e2fcb486d7acb45c6009a856f647071" dependencies: - babel-core "^6.23.0" - babel-runtime "^6.22.0" - core-js "^2.4.0" + babel-core "^6.26.0" + babel-runtime "^6.26.0" + core-js "^2.5.0" home-or-tmp "^2.0.0" - lodash "^4.2.0" + lodash "^4.17.4" mkdirp "^0.5.1" - source-map-support "^0.4.2" + source-map-support "^0.4.15" babel-runtime@^6.18.0, babel-runtime@^6.22.0: version "6.22.0" @@ -843,7 +914,14 @@ babel-runtime@^6.18.0, babel-runtime@^6.22.0: core-js "^2.4.0" regenerator-runtime "^0.10.0" -babel-template@^6.16.0, babel-template@^6.22.0, babel-template@^6.23.0: +babel-runtime@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" + dependencies: + core-js "^2.4.0" + regenerator-runtime "^0.11.0" + +babel-template@^6.16.0: version "6.23.0" resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.23.0.tgz#04d4f270adbb3aa704a8143ae26faa529238e638" dependencies: @@ -853,7 +931,17 @@ babel-template@^6.16.0, babel-template@^6.22.0, babel-template@^6.23.0: babylon "^6.11.0" lodash "^4.2.0" -babel-traverse@^6.18.0, babel-traverse@^6.22.0, babel-traverse@^6.23.0, babel-traverse@^6.23.1: +babel-template@^6.24.1, babel-template@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.26.0.tgz#de03e2d16396b069f46dd9fff8521fb1a0e35e02" + dependencies: + babel-runtime "^6.26.0" + babel-traverse "^6.26.0" + babel-types "^6.26.0" + babylon "^6.18.0" + lodash "^4.17.4" + +babel-traverse@^6.18.0, babel-traverse@^6.23.0: version "6.23.1" resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.23.1.tgz#d3cb59010ecd06a97d81310065f966b699e14f48" dependencies: @@ -867,7 +955,21 @@ babel-traverse@^6.18.0, babel-traverse@^6.22.0, babel-traverse@^6.23.0, babel-tr invariant "^2.2.0" lodash "^4.2.0" -babel-types@^6.18.0, babel-types@^6.19.0, babel-types@^6.22.0, babel-types@^6.23.0: +babel-traverse@^6.24.1, babel-traverse@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.26.0.tgz#46a9cbd7edcc62c8e5c064e2d2d8d0f4035766ee" + dependencies: + babel-code-frame "^6.26.0" + babel-messages "^6.23.0" + babel-runtime "^6.26.0" + babel-types "^6.26.0" + babylon "^6.18.0" + debug "^2.6.8" + globals "^9.18.0" + invariant "^2.2.2" + lodash "^4.17.4" + +babel-types@^6.18.0, babel-types@^6.19.0, babel-types@^6.23.0: version "6.23.0" resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.23.0.tgz#bb17179d7538bad38cd0c9e115d340f77e7e9acf" dependencies: @@ -876,10 +978,27 @@ babel-types@^6.18.0, babel-types@^6.19.0, babel-types@^6.22.0, babel-types@^6.23 lodash "^4.2.0" to-fast-properties "^1.0.1" -babylon@^6.11.0, babylon@^6.13.0, babylon@^6.15.0, babylon@^6.16.1: +babel-types@^6.24.1, babel-types@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497" + dependencies: + babel-runtime "^6.26.0" + esutils "^2.0.2" + lodash "^4.17.4" + to-fast-properties "^1.0.3" + +babylon@7.0.0-beta.32, babylon@^7.0.0-beta.31: + version "7.0.0-beta.32" + resolved "https://registry.yarnpkg.com/babylon/-/babylon-7.0.0-beta.32.tgz#e9033cb077f64d6895f4125968b37dc0a8c3bc6e" + +babylon@^6.11.0, babylon@^6.13.0, babylon@^6.15.0: version "6.16.1" resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.16.1.tgz#30c5a22f481978a9e7f8cdfdf496b11d94b404d3" +babylon@^6.18.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3" + backo2@1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/backo2/-/backo2-1.0.2.tgz#31ab1ac8b129363463e35b3ebb69f4dfcfba7947" @@ -953,7 +1072,7 @@ bluebird@^2.10.2: version "2.11.0" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-2.11.0.tgz#534b9033c022c9579c56ba3b3e5a5caafbb650e1" -bluebird@^3.0.5, bluebird@^3.1.1: +bluebird@^3.1.1: version "3.4.7" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.4.7.tgz#f72d760be09b7f76d08ed8fae98b289a8d05fab3" @@ -1191,6 +1310,14 @@ chalk@1.1.3, chalk@^1.0.0, chalk@^1.1.0, chalk@^1.1.1, chalk@^1.1.3: strip-ansi "^3.0.0" supports-color "^2.0.0" +chalk@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.3.0.tgz#b5ea48efc9c1793dccc9b4767c93914d3f2d52ba" + dependencies: + ansi-styles "^3.1.0" + escape-string-regexp "^1.0.5" + supports-color "^4.0.0" + chokidar@^1.4.1, chokidar@^1.4.3, chokidar@^1.6.0, chokidar@^1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-1.7.0.tgz#798e689778151c8076b4b360e5edd28cda2bb468" @@ -1280,6 +1407,12 @@ color-convert@^1.3.0: dependencies: color-name "^1.1.1" +color-convert@^1.9.0: + version "1.9.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.1.tgz#c1261107aeb2f294ebffec9ed9ecad529a6097ed" + dependencies: + color-name "^1.1.1" + color-name@^1.0.0, color-name@^1.1.1: version "1.1.2" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.2.tgz#5c8ab72b64bd2215d617ae9559ebb148475cf98d" @@ -1385,13 +1518,6 @@ concat-stream@^1.5.2: readable-stream "^2.2.2" typedarray "^0.0.6" -config-chain@~1.1.5: - version "1.1.11" - resolved "https://registry.yarnpkg.com/config-chain/-/config-chain-1.1.11.tgz#aba09747dfbe4c3e70e766a6e41586e1859fc6f2" - dependencies: - ini "^1.3.4" - proto-list "~1.2.1" - configstore@^1.0.0: version "1.4.0" resolved "https://registry.yarnpkg.com/configstore/-/configstore-1.4.0.tgz#c35781d0501d268c25c54b8b17f6240e8a4fb021" @@ -1450,9 +1576,9 @@ content-type@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.2.tgz#b7d113aee7a8dd27bd21133c4dc2529df1721eed" -convert-source-map@^1.1.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.3.0.tgz#e9f3e9c6e2728efc2676696a70eb382f73106a67" +convert-source-map@^1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.5.0.tgz#9acd70851c6d5dfdd93d9282e5edf94a03ff46b5" cookie-signature@1.0.6: version "1.0.6" @@ -1483,6 +1609,10 @@ core-js@^2.4.0, core-js@^2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.4.1.tgz#4de911e667b0eae9124e34254b53aea6fc618d3e" +core-js@^2.5.0: + version "2.5.1" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.1.tgz#ae6874dc66937789b80754ff5428df66819ca50b" + core-js@~2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.3.0.tgz#fab83fbb0b2d8dc85fa636c4b9d34c75420c6d65" @@ -1723,12 +1853,18 @@ debug@2.6.7: dependencies: ms "2.0.0" -debug@2.6.8, debug@^2.1.0, debug@^2.1.1, debug@^2.2.0, debug@^2.4.5, debug@^2.6.6, debug@^2.6.8: +debug@2.6.8, debug@^2.1.0, debug@^2.1.1, debug@^2.2.0, debug@^2.6.6, debug@^2.6.8: version "2.6.8" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.8.tgz#e731531ca2ede27d188222427da17821d68ff4fc" dependencies: ms "2.0.0" +debug@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" + dependencies: + ms "2.0.0" + decamelize@^1.0.0, decamelize@^1.1.1, decamelize@^1.1.2: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" @@ -1951,15 +2087,6 @@ ecc-jsbn@~0.1.1: dependencies: jsbn "~0.1.0" -editorconfig@^0.13.2: - version "0.13.2" - resolved "https://registry.yarnpkg.com/editorconfig/-/editorconfig-0.13.2.tgz#8e57926d9ee69ab6cb999f027c2171467acceb35" - dependencies: - bluebird "^3.0.5" - commander "^2.9.0" - lru-cache "^3.2.0" - sigmund "^1.0.1" - ee-first@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" @@ -2614,11 +2741,11 @@ flatten@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.2.tgz#dae46a9d78fbe25292258cc1e780a41d95c03782" -follow-redirects@^1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.2.3.tgz#01abaeca85e3609837d9fcda3167a7e42fdaca21" +follow-redirects@^1.2.5: + version "1.2.6" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.2.6.tgz#4dcdc7e4ab3dd6765a97ff89c3b4c258117c79bf" dependencies: - debug "^2.4.5" + debug "^3.1.0" for-each@~0.3.2: version "0.3.2" @@ -2816,7 +2943,11 @@ glob@^7.0.3, glob@^7.0.5: once "^1.3.0" path-is-absolute "^1.0.0" -globals@^9.0.0, globals@^9.14.0: +globals@^10.0.0: + version "10.4.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-10.4.0.tgz#5c477388b128a9e4c5c5d01c7a2aca68c68b2da7" + +globals@^9.0.0, globals@^9.14.0, globals@^9.18.0: version "9.18.0" resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" @@ -3158,7 +3289,7 @@ inherits@2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1" -ini@^1.3.4, ini@~1.3.0: +ini@~1.3.0: version "1.3.4" resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.4.tgz#0537cb79daf59b59a1a517dff706c86ec039162e" @@ -3190,7 +3321,7 @@ interpret@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.0.1.tgz#d579fb7f693b858004947af39fa0db49f795602c" -invariant@^2.2.0: +invariant@^2.2.0, invariant@^2.2.2: version "2.2.2" resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.2.tgz#9e1f56ac0acdb6bf303306f338be3b204ae60360" dependencies: @@ -3468,13 +3599,17 @@ istanbul-lib-coverage@^1.0.0, istanbul-lib-coverage@^1.0.0-alpha, istanbul-lib-c version "1.0.1" resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-1.0.1.tgz#f263efb519c051c5f1f3343034fc40e7b43ff212" +istanbul-lib-coverage@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-1.1.1.tgz#73bfb998885299415c93d38a3e9adf784a77a9da" + istanbul-lib-hook@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/istanbul-lib-hook/-/istanbul-lib-hook-1.0.0.tgz#fc5367ee27f59268e8f060b0c7aaf051d9c425c5" dependencies: append-transform "^0.4.0" -istanbul-lib-instrument@^1.3.0, istanbul-lib-instrument@^1.4.2: +istanbul-lib-instrument@^1.3.0: version "1.4.2" resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-1.4.2.tgz#0e2fdfac93c1dabf2e31578637dc78a19089f43e" dependencies: @@ -3486,6 +3621,18 @@ istanbul-lib-instrument@^1.3.0, istanbul-lib-instrument@^1.4.2: istanbul-lib-coverage "^1.0.0" semver "^5.3.0" +istanbul-lib-instrument@^1.7.5: + version "1.9.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-1.9.1.tgz#250b30b3531e5d3251299fdd64b0b2c9db6b558e" + dependencies: + babel-generator "^6.18.0" + babel-template "^6.16.0" + babel-traverse "^6.18.0" + babel-types "^6.18.0" + babylon "^6.18.0" + istanbul-lib-coverage "^1.1.1" + semver "^5.3.0" + istanbul-lib-report@^1.0.0-alpha.3: version "1.0.0-alpha.3" resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-1.0.0-alpha.3.tgz#32d5f6ec7f33ca3a602209e278b2e6ff143498af" @@ -3564,15 +3711,6 @@ js-base64@^2.1.9: version "2.1.9" resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.1.9.tgz#f0e80ae039a4bd654b5f281fc93f04a914a7fcce" -js-beautify@^1.6.3: - version "1.6.12" - resolved "https://registry.yarnpkg.com/js-beautify/-/js-beautify-1.6.12.tgz#78b75933505d376da6e5a28e9b7887e0094db8b5" - dependencies: - config-chain "~1.1.5" - editorconfig "^0.13.2" - mkdirp "~0.5.0" - nopt "~3.0.1" - js-cookie@^2.1.3: version "2.1.3" resolved "https://registry.yarnpkg.com/js-cookie/-/js-cookie-2.1.3.tgz#48071625217ac9ecfab8c343a13d42ec09ff0526" @@ -3924,10 +4062,6 @@ lodash.defaults@^3.1.2: lodash.assign "^3.0.0" lodash.restparam "^3.0.0" -lodash.get@4.4.2: - version "4.4.2" - resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" - lodash.get@^3.7.0: version "3.7.0" resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-3.7.0.tgz#3ce68ae2c91683b281cc5394128303cbf75e691f" @@ -3981,14 +4115,14 @@ lodash.words@^4.0.0: version "4.2.0" resolved "https://registry.yarnpkg.com/lodash.words/-/lodash.words-4.2.0.tgz#5ecfeaf8ecf8acaa8e0c8386295f1993c9cf4036" +lodash@4.17.4, lodash@^4.0.0, lodash@^4.11.1, lodash@^4.14.0, lodash@^4.17.2, lodash@^4.17.4, lodash@^4.2.0, lodash@^4.3.0, lodash@^4.5.0: + version "4.17.4" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" + lodash@^3.8.0: version "3.10.1" resolved "https://registry.yarnpkg.com/lodash/-/lodash-3.10.1.tgz#5bf45e8e49ba4189e17d482789dfd15bd140b7b6" -lodash@^4.0.0, lodash@^4.11.1, lodash@^4.14.0, lodash@^4.17.2, lodash@^4.17.4, lodash@^4.2.0, lodash@^4.3.0, lodash@^4.5.0: - version "4.17.4" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" - log4js@^0.6.31: version "0.6.38" resolved "https://registry.yarnpkg.com/log4js/-/log4js-0.6.38.tgz#2c494116695d6fb25480943d3fc872e662a522fd" @@ -4025,12 +4159,6 @@ lru-cache@2.2.x: version "2.2.4" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-2.2.4.tgz#6c658619becf14031d0d0b594b16042ce4dc063d" -lru-cache@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-3.2.0.tgz#71789b3b7f5399bec8565dda38aa30d2a097efee" - dependencies: - pseudomap "^1.0.1" - lru-cache@^4.0.1: version "4.0.2" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.0.2.tgz#1d17679c069cda5d040991a09dbc2c0db377e55e" @@ -4038,6 +4166,13 @@ lru-cache@^4.0.1: pseudomap "^1.0.1" yallist "^2.0.0" +lru-cache@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.1.tgz#622e32e82488b49279114a4f9ecf45e7cd6bba55" + dependencies: + pseudomap "^1.0.2" + yallist "^2.1.2" + macaddress@^0.2.8: version "0.2.8" resolved "https://registry.yarnpkg.com/macaddress/-/macaddress-0.2.8.tgz#5904dc537c39ec6dbefeae902327135fa8511f12" @@ -4356,7 +4491,7 @@ nodemon@^1.11.0: undefsafe "0.0.3" update-notifier "0.5.0" -nopt@3.x, nopt@~3.0.1: +nopt@3.x: version "3.0.6" resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9" dependencies: @@ -4674,7 +4809,7 @@ path-exists@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" -path-is-absolute@^1.0.0: +path-is-absolute@^1.0.0, path-is-absolute@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" @@ -5030,7 +5165,7 @@ postcss-zindex@^2.0.1: postcss "^5.0.4" uniqs "^2.0.0" -postcss@^5.0.10, postcss@^5.0.11, postcss@^5.0.12, postcss@^5.0.13, postcss@^5.0.14, postcss@^5.0.16, postcss@^5.0.2, postcss@^5.0.21, postcss@^5.0.4, postcss@^5.0.5, postcss@^5.0.6, postcss@^5.0.8, postcss@^5.2.16: +postcss@^5.0.10, postcss@^5.0.11, postcss@^5.0.12, postcss@^5.0.13, postcss@^5.0.14, postcss@^5.0.16, postcss@^5.0.2, postcss@^5.0.4, postcss@^5.0.5, postcss@^5.0.6, postcss@^5.0.8, postcss@^5.2.16: version "5.2.16" resolved "https://registry.yarnpkg.com/postcss/-/postcss-5.2.16.tgz#732b3100000f9ff8379a48a53839ed097376ad57" dependencies: @@ -5039,6 +5174,14 @@ postcss@^5.0.10, postcss@^5.0.11, postcss@^5.0.12, postcss@^5.0.13, postcss@^5.0 source-map "^0.5.6" supports-color "^3.2.3" +postcss@^6.0.8: + version "6.0.14" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.14.tgz#5534c72114739e75d0afcf017db853099f562885" + dependencies: + chalk "^2.3.0" + source-map "^0.6.1" + supports-color "^4.4.0" + prelude-ls@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" @@ -5051,6 +5194,10 @@ preserve@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" +prettier@^1.7.0: + version "1.8.2" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.8.2.tgz#bff83e7fd573933c607875e5ba3abbdffb96aeb8" + prismjs@^1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.6.0.tgz#118d95fb7a66dba2272e343b345f5236659db365" @@ -5061,6 +5208,10 @@ private@^0.1.6: version "0.1.7" resolved "https://registry.yarnpkg.com/private/-/private-0.1.7.tgz#68ce5e8a1ef0a23bb570cc28537b5332aba63ef1" +private@^0.1.7: + version "0.1.8" + resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" + process-nextick-args@~1.0.6: version "1.0.7" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3" @@ -5073,10 +5224,6 @@ progress@^1.1.8: version "1.1.8" resolved "https://registry.yarnpkg.com/progress/-/progress-1.1.8.tgz#e260c78f6161cdd9b0e56cc3e0a85de17c7a57be" -proto-list@~1.2.1: - version "1.2.4" - resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849" - proxy-addr@~1.1.5: version "1.1.5" resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-1.1.5.tgz#71c0ee3b102de3f202f3b64f608d173fcba1a918" @@ -5094,7 +5241,7 @@ ps-tree@^1.0.1: dependencies: event-stream "~3.3.0" -pseudomap@^1.0.1: +pseudomap@^1.0.1, pseudomap@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" @@ -5357,9 +5504,13 @@ regenerator-runtime@^0.10.0: version "0.10.1" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.10.1.tgz#257f41961ce44558b18f7814af48c17559f9faeb" -regenerator-transform@0.9.8: - version "0.9.8" - resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.9.8.tgz#0f88bb2bc03932ddb7b6b7312e68078f01026d6c" +regenerator-runtime@^0.11.0: + version "0.11.0" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.0.tgz#7e54fe5b5ccd5d6624ea6255c3473be090b802e1" + +regenerator-transform@^0.10.0: + version "0.10.1" + resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.10.1.tgz#1e4996837231da8b7f3cf4114d71b5691a0680dd" dependencies: babel-runtime "^6.18.0" babel-types "^6.19.0" @@ -5494,6 +5645,12 @@ resolve@^1.1.6, resolve@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.2.0.tgz#9589c3f2f6149d1417a40becc1663db6ec6bc26c" +resolve@^1.4.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.5.0.tgz#1f09acce796c9a762579f31b2c1cc4c3cddf9f36" + dependencies: + path-parse "^1.0.5" + resolve@~1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.4.0.tgz#a75be01c53da25d934a98ebd0e4c4a7312f92a86" @@ -5666,10 +5823,6 @@ shelljs@^0.7.5: interpret "^1.0.0" rechoir "^0.6.2" -sigmund@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/sigmund/-/sigmund-1.0.1.tgz#3ff21f198cad2175f9f3b781853fd94d0d19b590" - signal-exit@^3.0.0: version "3.0.2" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" @@ -5779,11 +5932,11 @@ source-list-map@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.0.tgz#aaa47403f7b245a92fbc97ea08f250d6087ed085" -source-map-support@^0.4.2: - version "0.4.11" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.11.tgz#647f939978b38535909530885303daf23279f322" +source-map-support@^0.4.15: + version "0.4.18" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.18.tgz#0286a6de8be42641338594e97ccea75f0a2c585f" dependencies: - source-map "^0.5.3" + source-map "^0.5.6" source-map@0.5.x, source-map@^0.5.0, source-map@^0.5.3, source-map@^0.5.6, source-map@~0.5.1, source-map@~0.5.3: version "0.5.6" @@ -5801,6 +5954,10 @@ source-map@^0.4.4: dependencies: amdefine ">=0.0.4" +source-map@^0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + source-map@~0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.2.0.tgz#dab73fbcfc2ba819b4de03bd6f6eaa48164b3f9d" @@ -5990,6 +6147,12 @@ supports-color@^3.1.0, supports-color@^3.1.1, supports-color@^3.1.2, supports-co dependencies: has-flag "^1.0.0" +supports-color@^4.0.0, supports-color@^4.4.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.5.0.tgz#be7a0de484dec5c5cddf8b3d59125044912f635b" + dependencies: + has-flag "^2.0.0" + supports-color@^4.2.1: version "4.2.1" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.2.1.tgz#65a4bb2631e90e02420dba5554c375a4754bb836" @@ -6070,9 +6233,9 @@ tar@^2.2.1: fstream "^1.0.2" inherits "2" -test-exclude@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-4.0.0.tgz#0ddc0100b8ae7e88b34eb4fd98a907e961991900" +test-exclude@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-4.1.1.tgz#4d84964b0966b0087ecc334a2ce002d3d9341e26" dependencies: arrify "^1.0.1" micromatch "^2.3.11" @@ -6160,6 +6323,14 @@ to-fast-properties@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.2.tgz#f3f5c0c3ba7299a7ef99427e44633257ade43320" +to-fast-properties@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" + +to-fast-properties@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" + touch@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/touch/-/touch-1.0.0.tgz#449cbe2dbae5a8c8038e30d71fa0ff464947c4de" @@ -6411,26 +6582,27 @@ void-elements@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-2.0.1.tgz#c066afb582bb1cb4128d60ea92392e94d5e9dbec" -vue-hot-reload-api@^2.0.11: - version "2.0.11" - resolved "https://registry.yarnpkg.com/vue-hot-reload-api/-/vue-hot-reload-api-2.0.11.tgz#bf26374fb73366ce03f799e65ef5dfd0e28a1568" +vue-hot-reload-api@^2.2.0: + version "2.2.4" + resolved "https://registry.yarnpkg.com/vue-hot-reload-api/-/vue-hot-reload-api-2.2.4.tgz#683bd1d026c0d3b3c937d5875679e9a87ec6cd8f" -vue-loader@^11.3.4: - version "11.3.4" - resolved "https://registry.yarnpkg.com/vue-loader/-/vue-loader-11.3.4.tgz#65e10a44ce092d906e14bbc72981dec99eb090d2" +vue-loader@^13.5.0: + version "13.5.0" + resolved "https://registry.yarnpkg.com/vue-loader/-/vue-loader-13.5.0.tgz#52f7b3790a267eff80012b77ea187a54586dd5d4" dependencies: consolidate "^0.14.0" hash-sum "^1.0.2" - js-beautify "^1.6.3" loader-utils "^1.1.0" - lru-cache "^4.0.1" - postcss "^5.0.21" + lru-cache "^4.1.1" + postcss "^6.0.8" postcss-load-config "^1.1.0" postcss-selector-parser "^2.0.0" - source-map "^0.5.6" - vue-hot-reload-api "^2.0.11" - vue-style-loader "^2.0.0" - vue-template-es2015-compiler "^1.2.2" + prettier "^1.7.0" + resolve "^1.4.0" + source-map "^0.6.1" + vue-hot-reload-api "^2.2.0" + vue-style-loader "^3.0.0" + vue-template-es2015-compiler "^1.6.0" vue-resource@^1.3.4: version "1.3.4" @@ -6438,31 +6610,31 @@ vue-resource@^1.3.4: dependencies: got "^7.0.0" -vue-style-loader@^2.0.0: - version "2.0.5" - resolved "https://registry.yarnpkg.com/vue-style-loader/-/vue-style-loader-2.0.5.tgz#f0efac992febe3f12e493e334edb13cd235a3d22" +vue-style-loader@^3.0.0: + version "3.0.3" + resolved "https://registry.yarnpkg.com/vue-style-loader/-/vue-style-loader-3.0.3.tgz#623658f81506aef9d121cdc113a4f5c9cac32df7" dependencies: hash-sum "^1.0.2" loader-utils "^1.0.2" -vue-template-compiler@^2.5.2: - version "2.5.2" - resolved "https://registry.yarnpkg.com/vue-template-compiler/-/vue-template-compiler-2.5.2.tgz#6f198ebc677b8f804315cd33b91e849315ae7177" +vue-template-compiler@^2.5.8: + version "2.5.8" + resolved "https://registry.yarnpkg.com/vue-template-compiler/-/vue-template-compiler-2.5.8.tgz#826ae77e1d5faa7fa5fca554f33872dde38de674" dependencies: de-indent "^1.0.2" he "^1.1.0" -vue-template-es2015-compiler@^1.2.2: - version "1.5.1" - resolved "https://registry.yarnpkg.com/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.5.1.tgz#0c36cc57aa3a9ec13e846342cb14a72fcac8bd93" +vue-template-es2015-compiler@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.6.0.tgz#dc42697133302ce3017524356a6c61b7b69b4a18" -vue@^2.5.2: - version "2.5.2" - resolved "https://registry.yarnpkg.com/vue/-/vue-2.5.2.tgz#fd367a87bae7535e47f9dc5c9ec3b496e5feb5a4" +vue@^2.5.8: + version "2.5.8" + resolved "https://registry.yarnpkg.com/vue/-/vue-2.5.8.tgz#f855c1c27255184a82225f4bef225473e8faf15b" -vuex@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/vuex/-/vuex-3.0.0.tgz#98b4b5c4954b1c1c1f5b29fa0476a23580315814" +vuex@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/vuex/-/vuex-3.0.1.tgz#e761352ebe0af537d4bb755a9b9dc4be3df7efd2" watchpack@^1.4.0: version "1.4.0" @@ -6696,7 +6868,7 @@ y18n@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41" -yallist@^2.0.0: +yallist@^2.0.0, yallist@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" |