Commit 15f10ec0 authored by Clement Ho's avatar Clement Ho

Merge branch 'master' into dispatcher-branches-create

parents acefbad2 b5cde6b6
......@@ -8,7 +8,8 @@
"plugins": [
["istanbul", {
"exclude": [
"spec/javascripts/**/*"
"spec/javascripts/**/*",
"app/assets/javascripts/locale/**/app.js"
]
}],
["transform-define", {
......
......@@ -10,7 +10,6 @@
],
"globals": {
"__webpack_public_path__": true,
"_": false,
"gl": false,
"gon": false,
"localStorage": false
......
......@@ -604,6 +604,7 @@ codequality:
paths: [codeclimate.json]
sast:
<<: *except-docs
image: registry.gitlab.com/gitlab-org/gl-sast:latest
before_script: []
script:
......@@ -623,6 +624,18 @@ qa:internal:
- bundle install
- bundle exec rspec
qa:selectors:
<<: *dedicated-runner
<<: *except-docs
stage: test
variables:
SETUP_DB: "false"
services: []
script:
- cd qa/
- bundle install
- bundle exec bin/qa Test::Sanity::Selectors
coverage:
<<: *dedicated-runner
<<: *except-docs-and-qa
......
......@@ -2,6 +2,19 @@
documentation](doc/development/changelog.md) for instructions on adding your own
entry.
## 10.3.4 (2018-01-10)
### Security (7 changes, 1 of them is from the community)
- Prevent a SQL injection in the MilestonesFinder.
- Fix RCE via project import mechanism.
- Prevent OAuth login POST requests when a provider has been disabled.
- Filter out sensitive fields from the project services API. (Robert Schilling)
- Check user authorization for source and target projects when creating a merge request.
- Fix path traversal in gitlab-ci.yml cache:key.
- Fix writable shared deploy keys.
## 10.3.3 (2018-01-02)
### Fixed (3 changes)
......@@ -180,6 +193,21 @@ entry.
- Clean up schema of the "merge_requests" table.
## 10.2.6 (2018-01-11)
### Security (9 changes, 1 of them is from the community)
- Fix writable shared deploy keys.
- Filter out sensitive fields from the project services API. (Robert Schilling)
- Fix RCE via project import mechanism.
- Fixed IPython notebook output not being sanitized.
- Prevent OAuth login POST requests when a provider has been disabled.
- Prevent a SQL injection in the MilestonesFinder.
- Check user authorization for source and target projects when creating a merge request.
- Fix path traversal in gitlab-ci.yml cache:key.
- Fix XSS vulnerability in pipeline job trace.
## 10.2.5 (2017-12-15)
### Fixed (8 changes)
......@@ -446,6 +474,20 @@ entry.
- Add Gitaly metrics to the performance bar.
## 10.1.6 (2018-01-11)
### Security (8 changes, 1 of them is from the community)
- Fix writable shared deploy keys.
- Filter out sensitive fields from the project services API. (Robert Schilling)
- Fix RCE via project import mechanism.
- Prevent OAuth login POST requests when a provider has been disabled.
- Prevent a SQL injection in the MilestonesFinder.
- Check user authorization for source and target projects when creating a merge request.
- Fix path traversal in gitlab-ci.yml cache:key.
- Fix XSS vulnerability in pipeline job trace.
## 10.1.5 (2017-12-07)
### Security (5 changes)
......
......@@ -385,9 +385,6 @@ gem 'ruby-prof', '~> 0.16.2'
# OAuth
gem 'oauth2', '~> 1.4'
# Soft deletion
gem 'paranoia', '~> 2.3.1'
# Health check
gem 'health_check', '~> 2.6.0'
......
......@@ -580,8 +580,6 @@ GEM
orm_adapter (0.5.0)
os (0.9.6)
parallel (1.12.0)
paranoia (2.3.1)
activerecord (>= 4.0, < 5.2)
parser (2.4.0.2)
ast (~> 2.3)
parslet (1.5.0)
......@@ -1117,7 +1115,6 @@ DEPENDENCIES
omniauth-twitter (~> 1.2.0)
omniauth_crowd (~> 2.2.0)
org-ruby (~> 0.9.12)
paranoia (~> 2.3.1)
peek (~> 1.0.1)
peek-gc (~> 0.0.2)
peek-host (~> 1.0.0)
......
app/assets/images/multi-editor-on.png

5.34 KB | W: | H:

app/assets/images/multi-editor-on.png

3.88 KB | W: | H:

app/assets/images/multi-editor-on.png
app/assets/images/multi-editor-on.png
app/assets/images/multi-editor-on.png
app/assets/images/multi-editor-on.png
  • 2-up
  • Swipe
  • Onion skin
......@@ -4,6 +4,8 @@ import { visitUrl } from '../lib/utils/url_utility';
import { HIDDEN_CLASS } from '../lib/utils/constants';
import csrf from '../lib/utils/csrf';
Dropzone.autoDiscover = false;
function toggleLoading($el, $icon, loading) {
if (loading) {
$el.disable();
......
/* eslint-disable comma-dangle, space-before-function-paren, one-var */
/* global Sortable */
import Sortable from 'vendor/Sortable';
import Vue from 'vue';
import AccessorUtilities from '../../lib/utils/accessor';
import boardList from './board_list';
......
/* global Sortable */
import Sortable from 'vendor/Sortable';
import boardNewIssue from './board_new_issue';
import boardCard from './board_card.vue';
import eventHub from '../eventhub';
......
......@@ -46,14 +46,15 @@
));
const extraCostParagraph = sprintf(
_.escape(s__(`ClusterIntegration|%{boldNotice} This will add some
extra resources like a load balancer,
which incur additional costs. See %{pricingLink}`)),
{
_.escape(s__(
`ClusterIntegration|%{boldNotice} This will add some extra resources
like a load balancer, which may incur additional costs depending on
the hosting provider Kubernetes is installed on. If you are using GKE,
you can %{pricingLink}.`,
)), {
boldNotice: `<strong>${_.escape(s__('ClusterIntegration|Note:'))}</strong>`,
pricingLink: `<a href="https://cloud.google.com/compute/pricing#lb" target="_blank" rel="noopener noreferrer">
${_.escape(s__('ClusterIntegration|GKE pricing'))}
</a>`,
${_.escape(s__('ClusterIntegration|check the pricing here'))}</a>`,
},
false,
);
......
/* eslint-disable no-new */
import _ from 'underscore';
import Flash from './flash';
import DropLab from './droplab/drop_lab';
import ISetter from './droplab/plugins/input_setter';
......
This diff is collapsed.
......@@ -3,6 +3,8 @@ import _ from 'underscore';
import './preview_markdown';
import csrf from './lib/utils/csrf';
Dropzone.autoDiscover = false;
export default function dropzoneInput(form) {
const divHover = '<div class="div-dropzone-hover"></div>';
const iconPaperclip = '<i class="fa fa-paperclip div-dropzone-icon"></i>';
......
/**
* Common code between environmets app and folder view
*/
import _ from 'underscore';
import Visibility from 'visibilityjs';
import Poll from '../../lib/utils/poll';
import {
......
import _ from 'underscore';
import DropLab from '~/droplab/drop_lab';
import FilteredSearchContainer from './container';
......
import _ from 'underscore';
import { visitUrl } from '../lib/utils/url_utility';
import Flash from '../flash';
import FilteredSearchContainer from './container';
......
import _ from 'underscore';
import AjaxCache from '../lib/utils/ajax_cache';
import Flash from '../flash';
import FilteredSearchContainer from './container';
......
<script>
/* global Flash */
import { s__ } from '~/locale';
import loadingIcon from '~/vue_shared/components/loading_icon.vue';
import modal from '~/vue_shared/components/modal.vue';
import { getParameterByName } from '~/lib/utils/common_utils';
import { mergeUrlParams } from '~/lib/utils/url_utility';
import eventHub from '../event_hub';
import { getParameterByName } from '../../lib/utils/common_utils';
import loadingIcon from '../../vue_shared/components/loading_icon.vue';
import { COMMON_STR } from '../constants';
import { mergeUrlParams } from '../../lib/utils/url_utility';
import groupsComponent from './groups.vue';
export default {
components: {
loadingIcon,
modal,
groupsComponent,
},
props: {
......@@ -32,6 +36,10 @@ export default {
isLoading: true,
isSearchEmpty: false,
searchEmptyMessage: '',
showModal: false,
groupLeaveConfirmationMessage: '',
targetGroup: null,
targetParentGroup: null,
};
},
computed: {
......@@ -48,7 +56,7 @@ export default {
eventHub.$on('fetchPage', this.fetchPage);
eventHub.$on('toggleChildren', this.toggleChildren);
eventHub.$on('leaveGroup', this.leaveGroup);
eventHub.$on('showLeaveGroupModal', this.showLeaveGroupModal);
eventHub.$on('updatePagination', this.updatePagination);
eventHub.$on('updateGroups', this.updateGroups);
},
......@@ -58,7 +66,7 @@ export default {
beforeDestroy() {
eventHub.$off('fetchPage', this.fetchPage);
eventHub.$off('toggleChildren', this.toggleChildren);
eventHub.$off('leaveGroup', this.leaveGroup);
eventHub.$off('showLeaveGroupModal', this.showLeaveGroupModal);
eventHub.$off('updatePagination', this.updatePagination);
eventHub.$off('updateGroups', this.updateGroups);
},
......@@ -141,14 +149,23 @@ export default {
parentGroup.isOpen = false;
}
},
leaveGroup(group, parentGroup) {
const targetGroup = group;
targetGroup.isBeingRemoved = true;
this.service.leaveGroup(targetGroup.leavePath)
showLeaveGroupModal(group, parentGroup) {
this.targetGroup = group;
this.targetParentGroup = parentGroup;
this.showModal = true;
this.groupLeaveConfirmationMessage = s__(`GroupsTree|Are you sure you want to leave the "${group.fullName}" group?`);
},
hideLeaveGroupModal() {
this.showModal = false;
},
leaveGroup() {
this.showModal = false;
this.targetGroup.isBeingRemoved = true;
this.service.leaveGroup(this.targetGroup.leavePath)
.then(res => res.json())
.then((res) => {
$.scrollTo(0);
this.store.removeGroup(targetGroup, parentGroup);
this.store.removeGroup(this.targetGroup, this.targetParentGroup);
Flash(res.notice, 'notice');
})
.catch((err) => {
......@@ -157,7 +174,7 @@ export default {
message = COMMON_STR.LEAVE_FORBIDDEN;
}
Flash(message);
targetGroup.isBeingRemoved = false;
this.targetGroup.isBeingRemoved = false;
});
},
updatePagination(headers) {
......@@ -190,5 +207,14 @@ export default {
:search-empty-message="searchEmptyMessage"
:page-info="pageInfo"
/>
<modal
v-show="showModal"
:primary-button-label="__('Leave')"
kind="warning"
:title="__('Are you sure?')"
:text="groupLeaveConfirmationMessage"
@cancel="hideLeaveGroupModal"
@submit="leaveGroup"
/>
</div>
</template>
<script>
import { s__ } from '~/locale';
import tooltip from '~/vue_shared/directives/tooltip';
import icon from '~/vue_shared/components/icon.vue';
import modal from '~/vue_shared/components/modal.vue';
import eventHub from '../event_hub';
import { COMMON_STR } from '../constants';
import tooltip from '~/vue_shared/directives/tooltip';
import icon from '~/vue_shared/components/icon.vue';
import eventHub from '../event_hub';
import { COMMON_STR } from '../constants';
export default {
components: {
icon,
modal,
export default {
components: {
icon,
},
directives: {
tooltip,
},
props: {
parentGroup: {
type: Object,
required: false,
default: () => ({}),
},
directives: {
tooltip,
group: {
type: Object,
required: true,
},
props: {
parentGroup: {
type: Object,
required: false,
default: () => ({}),
},
group: {
type: Object,
required: true,
},
},
computed: {
leaveBtnTitle() {
return COMMON_STR.LEAVE_BTN_TITLE;
},
data() {
return {
modalStatus: false,
};
editBtnTitle() {
return COMMON_STR.EDIT_BTN_TITLE;
},
computed: {
leaveBtnTitle() {
return COMMON_STR.LEAVE_BTN_TITLE;
},
editBtnTitle() {
return COMMON_STR.EDIT_BTN_TITLE;
},
leaveConfirmationMessage() {
return s__(`GroupsTree|Are you sure you want to leave the "${this.group.fullName}" group?`);
},
},
methods: {
onLeaveGroup() {
eventHub.$emit('showLeaveGroupModal', this.group, this.parentGroup);
},
methods: {
onLeaveGroup() {
this.modalStatus = true;
},
leaveGroup() {
this.modalStatus = false;
eventHub.$emit('leaveGroup', this.group, this.parentGroup);
},
},
};
},
};
</script>
<template>
......@@ -78,14 +63,5 @@
class="leave-group btn no-expand">
<icon name="leave"/>
</a>
<modal
v-show="modalStatus"
:primary-button-label="__('Leave')"
kind="warning"
:title="__('Are you sure?')"
:text="__('Are you sure you want to leave this group?')"
:body="leaveConfirmationMessage"
@submit="leaveGroup"
/>
</div>
</template>
import _ from 'underscore';
import DecorationsController from './decorations/controller';
import DirtyDiffController from './diff/controller';
import Disposable from './common/disposable';
......
import _ from 'underscore';
export const dataStructure = () => ({
id: '',
key: '',
......
/* eslint-disable comma-dangle, class-methods-use-this, no-underscore-dangle, no-param-reassign, no-unused-vars, consistent-return, func-names, space-before-function-paren, max-len */
/* global Sortable */
import Sortable from 'vendor/Sortable';
import Flash from './flash';
......
This diff is collapsed.
/* global Sortable */
import Flash from './flash';
export default class Milestone {
......
import { truncate } from './lib/utils/text_utility';
import { truncate } from '../../../lib/utils/text_utility';
const MAX_MESSAGE_LENGTH = 500;
const MESSAGE_CELL_SELECTOR = '.abuse-reports .message';
......
import AbuseReports from './abuse_reports';
export default () => new AbuseReports();
import { refreshCurrentPage } from './lib/utils/url_utility';
import { refreshCurrentPage } from '../../lib/utils/url_utility';
function showBlacklistType() {
if ($('input[name="blacklist_type"]:checked').val() === 'file') {
......
import _ from 'underscore';
export default function initBroadcastMessagesForm() {
$('input#broadcast_message_color').on('input', function onMessageColorInput() {
const previewColor = $(this).val();
......
import initBroadcastMessagesForm from './broadcast_message';
export default () => initBroadcastMessagesForm();
import initUsagePing from './usage_ping';
export default () => initUsagePing();
import groupAvatar from '../../../../group_avatar';
export default () => groupAvatar();
import BindInOut from '../../../../behaviors/bind_in_out';
import Group from '../../../../group';
import groupAvatar from '../../../../group_avatar';
export default () => {
BindInOut.initAll();
new Group(); // eslint-disable-line no-new
groupAvatar();
};
import UsersSelect from '../../../../users_select';
export default () => new UsersSelect();
import DueDateSelectors from '../../../due_date_select';
export default () => new DueDateSelectors();
import initAdmin from './admin';
export default () => initAdmin();
import Labels from '../../../../labels';
export default () => new Labels();
import Labels from '../../../../labels';
export default () => new Labels();
import ProjectsList from '../../../projects_list';
import NamespaceSelect from '../../../namespace_select';
export default () => {
new ProjectsList(); // eslint-disable-line no-new
document.querySelectorAll('.js-namespace-select')
.forEach(dropdown => new NamespaceSelect({ dropdown }));
};
import Activities from '~/activities';
export default () => new Activities();
import projectSelect from '~/project_select';
import initLegacyFilters from '~/init_legacy_filters';
export default () => {
projectSelect();
initLegacyFilters();
};
import GroupsList from '~/groups_list';
import Landing from '~/landing';
export default function () {
new GroupsList(); // eslint-disable-line no-new
const landingElement = document.querySelector('.js-explore-groups-landing');
if (!landingElement) return;
const exploreGroupsLanding = new Landing(
landingElement,
landingElement.querySelector('.dismiss-button'),
'explore_groups_landing_dismissed',
);
exploreGroupsLanding.toggle();
}
import ProjectsList from '~/projects_list';
export default () => new ProjectsList();
import VersionCheckImage from '../../version_check_image';
export default () => VersionCheckImage.bindErrorEvent($('img.js-version-status-badge'));
import NotificationsForm from '../../../notifications_form';
import notificationsDropdown from '../../../notifications_dropdown';
export default () => {
new NotificationsForm(); // eslint-disable-line no-new
notificationsDropdown();
};
import DueDateSelectors from '../../../due_date_select';
export default () => new DueDateSelectors();
import Activities from '~/activities';
import ShortcutsNavigation from '~/shortcuts_navigation';
export default function () {
new Activities(); // eslint-disable-line no-new
new ShortcutsNavigation(); // eslint-disable-line no-new
}
import BuildArtifacts from '~/build_artifacts';
import ShortcutsNavigation from '~/shortcuts_navigation';
export default function () {
new ShortcutsNavigation(); // eslint-disable-line no-new
new BuildArtifacts(); // eslint-disable-line no-new
}
import BlobViewer from '~/blob/viewer/index';
import ShortcutsNavigation from '~/shortcuts_navigation';
export default function () {
new ShortcutsNavigation(); // eslint-disable-line no-new
new BlobViewer(); // eslint-disable-line no-new
}
import UsersSelect from '~/users_select';
import ShortcutsNavigation from '~/shortcuts_navigation';
export default () => {
new UsersSelect(); // eslint-disable-line no-new
new ShortcutsNavigation(); // eslint-disable-line no-new
};
import Pipelines from '../../../../pipelines';
export default () => {
const { controllerAction } = document.querySelector('.js-pipeline-container').dataset;
const pipelineStatusUrl = `${document.querySelector('.js-pipeline-tab-link a').getAttribute('href')}/status.json`;
new Pipelines({ // eslint-disable-line no-new
initTabs: true,
pipelineStatusUrl,
tabsOptions: {
action: controllerAction,
defaultAction: 'pipelines',
parentEl: '.pipelines-tabs',
},
});
};
import NewBranchForm from '../../../../new_branch_form';
export default () => {
new NewBranchForm($('.js-new-pipeline-form')); // eslint-disable-line no-new
};
import memberExpirationDate from '../../../member_expiration_date';
import UsersSelect from '../../../users_select';
import groupsSelect from '../../../groups_select';
import Members from '../../../members';
export default () => {
memberExpirationDate('.js-access-expiration-date-groups');
groupsSelect();
memberExpirationDate();
new Members(); // eslint-disable-line no-new
new UsersSelect(); // eslint-disable-line no-new
};
import Search from './search';
export default () => new Search();
import Flash from './flash';
import Api from './api';
import Flash from '~/flash';
import Api from '~/api';
export default class Search {
constructor() {
......
import UsernameValidator from './username_validator';
import SigninTabsMemoizer from './signin_tabs_memoizer';
import OAuthRememberMe from './oauth_remember_me';
export default () => {
new UsernameValidator(); // eslint-disable-line no-new
new SigninTabsMemoizer(); // eslint-disable-line no-new
new OAuthRememberMe({ // eslint-disable-line no-new
container: $('.omniauth-container'),
}).bindEvents();
};
/* eslint no-param-reassign: ["error", { "props": false }]*/
/* eslint no-new: "off" */
import AccessorUtilities from './lib/utils/accessor';
import AccessorUtilities from '~/lib/utils/accessor';
/**
* Memorize the last selected tab after reloading a page.
......
import _ from 'underscore';
import Vue from 'vue';
import VueResource from 'vue-resource';
......
/* global Mousetrap */
import Mousetrap from 'mousetrap';
import { getLocationHash, visitUrl } from './lib/utils/url_utility';
import Shortcuts from './shortcuts';
......
/* global Mousetrap */
import Mousetrap from 'mousetrap';
import ShortcutsNavigation from './shortcuts_navigation';
export default class ShortcutsFindFile extends ShortcutsNavigation {
......
/* global Mousetrap */
import Mousetrap from 'mousetrap';
import _ from 'underscore';
import 'mousetrap';
import Sidebar from './right_sidebar';
import ShortcutsNavigation from './shortcuts_navigation';
import { CopyAsGFM } from './behaviors/copy_as_gfm';
......
/* global Mousetrap */
import Mousetrap from 'mousetrap';
import findAndFollowLink from './shortcuts_dashboard_navigation';
import Shortcuts from './shortcuts';
......
/* global Mousetrap */
import Mousetrap from 'mousetrap';
import ShortcutsNavigation from './shortcuts_navigation';
export default class ShortcutsNetwork extends ShortcutsNavigation {
......
/* eslint-disable class-methods-use-this */
/* global Mousetrap */
import Mousetrap from 'mousetrap';
import ShortcutsNavigation from './shortcuts_navigation';
import findAndFollowLink from './shortcuts_dashboard_navigation';
export default class ShortcutsWiki extends ShortcutsNavigation {
constructor() {
super();
Mousetrap.bind('e', this.editWiki);
Mousetrap.bind('e', ShortcutsWiki.editWiki);
}
editWiki() {
static editWiki() {
findAndFollowLink('.js-wiki-edit');
}
}
<script>
import tooltip from '../directives/tooltip';
/**
* Falls back to the code used in `copy_to_clipboard.js`
*/
export default {
name: 'ClipboardButton',
directives: {
tooltip,
},
props: {
text: {
type: String,
......@@ -14,6 +18,16 @@
type: String,
required: true,
},
tooltipPlacement: {
type: String,
required: false,
default: 'top',
},
tooltipContainer: {
type: [String, Boolean],
required: false,
default: false,
},
},
};
</script>
......@@ -22,8 +36,11 @@
<button
type="button"
class="btn btn-transparent btn-clipboard"
:data-title="title"
:title="title"
:data-clipboard-text="text"
v-tooltip
:data-container="tooltipContainer"
:data-placement="tooltipPlacement"
>
<i
aria-hidden="true"
......
/* eslint-disable func-names, space-before-function-paren, wrap-iife, prefer-arrow-callback, no-unused-vars, consistent-return, camelcase, comma-dangle, max-len, class-methods-use-this */
/* global Mousetrap */
// Zen Mode (full screen) textarea
//
......@@ -8,9 +7,11 @@
import 'vendor/jquery.scrollTo';
import Dropzone from 'dropzone';
import 'mousetrap';
import Mousetrap from 'mousetrap';
import 'mousetrap/plugins/pause/mousetrap-pause';
Dropzone.autoDiscover = false;
//
// ### Events
//
......
......@@ -18,14 +18,9 @@
margin: $gl-padding 0;
&.limited-width-container .file-content {
max-width: $limited-layout-width-sm;
max-width: $limited-layout-width;
margin-left: auto;
margin-right: auto;
@media (min-width: $screen-md-min) {
padding-top: 64px;
padding-bottom: 64px;
}
}
}
......@@ -128,7 +123,7 @@
}
&.wiki {
padding: 30px $gl-padding;
padding: $gl-padding;
}
&.blob-no-preview {
......
......@@ -651,12 +651,18 @@
min-width: 0;
}
.diff-changed-file-name {
.diff-changed-file-name,
.diff-changed-blank-file-name {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.diff-changed-blank-file-name {
color: $gl-text-color-tertiary;
font-style: italic;
}
.diff-changed-file-path {
color: $gl-text-color-tertiary;
}
......
......@@ -798,7 +798,6 @@ button.mini-pipeline-graph-dropdown-toggle {
// link to the build
.mini-pipeline-graph-dropdown-item {
padding: 3px 7px 4px;
align-items: center;
clear: both;
display: flex;
......
......@@ -16,12 +16,6 @@
display: inline-block;
}
@media (min-width: $screen-md-min) {
.blob-viewer[data-type="rich"] {
margin: 20px;
}
}
.ide-view {
display: flex;
height: calc(100vh - #{$header-height});
......
......@@ -65,6 +65,7 @@ class Admin::RunnersController < Admin::ApplicationController
else
Project.all
end
@projects = @projects.where.not(id: runner.projects.select(:id)) if runner.projects.any?
@projects = @projects.page(params[:page]).per(30)
end
......
......@@ -8,6 +8,7 @@ module GroupTree
# Only show root groups if no parent-id is given
groups.where(parent_id: params[:parent_id])
end
@groups = @groups.with_selects_for_list(archived: params[:archived])
.sort(@sort = params[:sort])
.page(params[:page])
......
......@@ -32,6 +32,7 @@ module RoutableActions
if canonical_path.casecmp(requested_full_path) != 0
flash[:notice] = "#{routable.class.to_s.titleize} '#{requested_full_path}' was moved to '#{canonical_path}'. Please update any links and bookmarks that may still have the old path."
end
redirect_to build_canonical_path(routable)
end
end
......
......@@ -12,6 +12,7 @@ class MetricsController < ActionController::Base
)
"# Metrics are disabled, see: #{help_page}\n"
end
render text: response, content_type: 'text/plain; version=0.0.4'
end
......
......@@ -83,6 +83,7 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
if ticket
handle_service_ticket oauth['provider'], ticket
end
handle_omniauth
end
......@@ -90,6 +91,7 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
if params['sid']
handle_service_ticket oauth['provider'], params['sid']
end
handle_omniauth
end
......@@ -124,6 +126,7 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
# Only allow properly saved users to login.
if @user.persisted? && @user.valid?
log_audit_event(@user, with: oauth['provider'])
if @user.two_factor_enabled?
params[:remember_me] = '1' if remember_me?
prompt_for_two_factor(@user)
......
......@@ -150,6 +150,7 @@ class Projects::BlobController < Projects::ApplicationController
if params[:file].present?
params[:file_name] = params[:file].original_filename
end
File.join(@path, params[:file_name])
elsif params[:file_path].present?
params[:file_path]
......
class Projects::Clusters::GcpController < Projects::ApplicationController
before_action :authorize_read_cluster!
before_action :authorize_google_api, except: [:login]
before_action :authorize_google_project_billing, only: [:new]
before_action :authorize_google_project_billing, only: [:new, :create]
before_action :authorize_create_cluster!, only: [:new, :create]
before_action :verify_billing, only: [:create]
def login
begin
......@@ -23,24 +24,34 @@ class Projects::Clusters::GcpController < Projects::ApplicationController
end
def create
@cluster = ::Clusters::CreateService
.new(project, current_user, create_params)
.execute(token_in_session)
if @cluster.persisted?
redirect_to project_cluster_path(project, @cluster)
else
render :new
end
end
private
def verify_billing
case google_project_billing_status
when 'true'
@cluster = ::Clusters::CreateService
.new(project, current_user, create_params)
.execute(token_in_session)
return redirect_to project_cluster_path(project, @cluster) if @cluster.persisted?
return
when 'false'
flash[:error] = _('Please enable billing for one of your projects to be able to create a cluster.')
flash[:alert] = _('Please <a href=%{link_to_billing} target="_blank" rel="noopener noreferrer">enable billing for one of your projects to be able to create a cluster</a>, then try again.').html_safe % { link_to_billing: "https://console.cloud.google.com/freetrial?utm_campaign=2018_cpanel&utm_source=gitlab&utm_medium=referral" }
else
flash[:error] = _('We could not verify that one of your projects on GCP has billing enabled. Please try again.')
flash[:alert] = _('We could not verify that one of your projects on GCP has billing enabled. Please try again.')
end
@cluster = ::Clusters::Cluster.new(create_params)
render :new
end
private
def create_params
params.require(:cluster).permit(
:enabled,
......
......@@ -27,6 +27,7 @@ class Projects::DeployKeysController < Projects::ApplicationController
unless @key.valid? && @project.deploy_keys << @key
flash[:alert] = @key.errors.full_messages.join(', ').html_safe
end
redirect_to_repository_settings(@project)
end
......
......@@ -21,6 +21,7 @@ class Projects::HooksController < Projects::ApplicationController
@hooks = @project.hooks.select(&:persisted?)
flash[:alert] = @hook.errors.full_messages.join.html_safe
end
redirect_to project_settings_integrations_path(@project)
end
......
......@@ -48,6 +48,7 @@ class Projects::MergeRequests::CreationsController < Projects::MergeRequests::Ap
else
[]
end
@diff_notes_disabled = true
@environment = @merge_request.environments_for(current_user).last
......
......@@ -203,6 +203,7 @@ class ProjectsController < Projects::ApplicationController
else
flash[:alert] = _("Project export could not be deleted.")
end
redirect_to(edit_project_path(@project))
end
......
......@@ -28,6 +28,7 @@ class SessionsController < Devise::SessionsController
resource.update_attributes(reset_password_token: nil,
reset_password_sent_at: nil)
end
# hide the signed-in notification
flash[:notice] = nil
log_audit_event(current_user, resource, with: authentication_method)
......
......@@ -63,6 +63,7 @@ class GroupDescendantsFinder
groups_table = Group.arel_table
visible_to_user = groups_table[:visibility_level]
.in(Gitlab::VisibilityLevel.levels_for_user(current_user))
if current_user
authorized_groups = GroupsFinder.new(current_user,
all_available: false)
......@@ -115,6 +116,7 @@ class GroupDescendantsFinder
else
direct_child_groups
end
groups.with_selects_for_list(archived: params[:archived]).order_by(sort)
end
......@@ -140,6 +142,7 @@ class GroupDescendantsFinder
else
direct_child_projects
end
projects.with_route.order_by(sort)
end
......
......@@ -34,6 +34,7 @@ class GroupProjectsFinder < ProjectsFinder
else
collection_without_user
end
union(projects)
end
......
......@@ -46,7 +46,7 @@ module BlobHelper
end
def ide_edit_text
"#{_('Multi Edit')} <span class='label label-primary'>#{_('Beta')}</span>".html_safe
"#{_('Web IDE')}"
end
def ide_blob_link(project = @project, ref = @ref, path = @path, options = {})
......
......@@ -203,6 +203,7 @@ module MarkupHelper
node.content = node.content.truncate(num_remaining)
truncated = true
end
content_length += node.content.length
end
......
......@@ -12,6 +12,7 @@ module NavHelper
current_path?('projects/merge_requests/conflicts#show') ||
current_path?('issues#show') ||
current_path?('milestones#show')
if cookies[:collapsed_gutter] == 'true'
%w[page-gutter right-sidebar-collapsed]
else
......
......@@ -89,6 +89,7 @@ module SnippetsHelper
snippet_chunk = [lined_content[line_number]]
snippet_start_line = line_number
end
last_line = line_number
end
# Add final chunk to chunk array
......
......@@ -58,6 +58,7 @@ module SubmoduleHelper
url_no_dotgit = url.chomp('.git')
return true if url_no_dotgit == [Gitlab.config.gitlab.url, '/', namespace, '/',
project].join('')
url_with_dotgit = url_no_dotgit + '.git'
url_with_dotgit == Gitlab::Shell.new.url_to_repo([namespace, '/', project].join(''))
end
......
......@@ -30,6 +30,7 @@ module TodosHelper
else
todo.target_reference
end
link_to text, todo_target_path(todo), class: 'has-tooltip', title: todo.target.title
end
......
......@@ -418,6 +418,7 @@ class ApplicationSetting < ActiveRecord::Base
super(group_full_path)
Gitlab::PerformanceBar.expire_allowed_user_ids_cache
end
return
end
......
......@@ -2,8 +2,9 @@ module Ci
class PipelineSchedule < ActiveRecord::Base
extend Gitlab::Ci::Model
include Importable
include IgnorableColumn
acts_as_paranoid
ignore_column :deleted_at
belongs_to :project
belongs_to :owner, class_name: 'User'
......
module Ci
class Trigger < ActiveRecord::Base
extend Gitlab::Ci::Model
include IgnorableColumn
acts_as_paranoid
ignore_column :deleted_at
belongs_to :project
belongs_to :owner, class_name: "User"
......
......@@ -10,7 +10,6 @@ module InternalId
if iid.blank?
parent = project || group
records = parent.public_send(self.class.name.tableize) # rubocop:disable GitlabSecurity/PublicSend
records = records.with_deleted if self.paranoid?
max_iid = records.maximum(:iid)
self.iid = max_iid.to_i + 1
......
......@@ -314,6 +314,7 @@ module Issuable
includes = []
includes << :author unless notes.authors_loaded?
includes << :award_emoji unless notes.award_emojis_loaded?
if includes.any?
notes.includes(includes)
else
......
......@@ -25,6 +25,7 @@ module LoadedInGroupList
base_count = projects.project(Arel.star.count.as('preloaded_project_count'))
.where(projects[:namespace_id].eq(namespaces[:id]))
if archived == 'only'
base_count.where(projects[:archived].eq(true))
elsif Gitlab::Utils.to_boolean(archived)
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment