summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG4
-rw-r--r--Gemfile4
-rw-r--r--Gemfile.lock10
-rw-r--r--PROCESS.md6
-rw-r--r--app/assets/javascripts/application.js.coffee1
-rw-r--r--app/assets/javascripts/merge_request_tabs.js.coffee13
-rw-r--r--app/assets/stylesheets/generic/header.scss7
-rw-r--r--app/assets/stylesheets/pages/diff.scss114
-rw-r--r--app/assets/stylesheets/pages/merge_requests.scss18
-rw-r--r--app/helpers/labels_helper.rb3
-rw-r--r--app/helpers/milestones_helper.rb3
-rw-r--r--app/models/group_milestone.rb2
-rw-r--r--app/models/label.rb4
-rw-r--r--app/models/milestone.rb6
-rw-r--r--app/views/admin/users/index.html.haml14
-rw-r--r--app/views/profiles/keys/_key_details.html.haml5
-rw-r--r--app/views/projects/diffs/_file.html.haml2
-rw-r--r--app/views/projects/forks/new.html.haml63
-rw-r--r--app/views/shared/issuable/_filter.html.haml4
-rw-r--r--doc/raketasks/user_management.md14
-rw-r--r--doc/release/monthly.md13
-rw-r--r--lib/gitlab/backend/shell.rb3
-rw-r--r--lib/tasks/gitlab/two_factor.rake23
-rw-r--r--spec/lib/gitlab/backend/shell_spec.rb13
24 files changed, 230 insertions, 119 deletions
diff --git a/CHANGELOG b/CHANGELOG
index b1a35c3c2ab..a3d796bea66 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,6 +1,7 @@
Please view this file on the master branch, on stable branches it's out of date.
v 8.1.0 (unreleased)
+ - Make diff file view easier to use on mobile screens (Stan Hu)
- Add support for creating directories from Files page (Stan Hu)
- Allow removing of project without confirmation when JavaScript is disabled (Stan Hu)
- Support filtering by "Any" milestone or issue and fix "No Milestone" and "No Label" filters (Stan Hu)
@@ -41,6 +42,9 @@ v 8.1.0 (unreleased)
- Move CI services page to project settings area
- Add "Quick Submit" behavior to input fields throughout the application. Use
Cmd+Enter on Mac and Ctrl+Enter on Windows/Linux.
+ - Fix position of hamburger in header for smaller screens (Han Loong Liauw)
+ - Fix bug where Emojis in Markdown would truncate remaining text (Sakata Sinji)
+ - Persist filters when sorting on admin user page (Jerry Lukins)
v 8.0.4
- Fix Message-ID header to be RFC 2111-compliant to prevent e-mails being dropped (Stan Hu)
diff --git a/Gemfile b/Gemfile
index 044dc30ecd4..e8cdb7a4a97 100644
--- a/Gemfile
+++ b/Gemfile
@@ -128,7 +128,6 @@ gem 'after_commit_queue'
gem 'acts-as-taggable-on', '~> 3.4'
# Background jobs
-gem 'slim', '~> 2.0.2'
gem 'sinatra', '~> 1.4.4', require: nil
gem 'sidekiq', '3.3.0'
gem 'sidetiq', '~> 0.6.3'
@@ -300,9 +299,6 @@ gem 'activerecord-deprecated_finders', '~> 1.0.3'
gem 'activerecord-session_store', '~> 0.1.0'
gem "nested_form", '~> 0.3.2'
-# Scheduled
-gem 'whenever', '~> 0.8.4', require: false
-
# OAuth
gem 'oauth2', '~> 1.0.0'
diff --git a/Gemfile.lock b/Gemfile.lock
index f716c0254ec..9911904d304 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -105,7 +105,6 @@ GEM
celluloid (0.16.0)
timers (~> 4.0.0)
charlock_holmes (0.6.9.4)
- chronic (0.10.2)
chunky_png (1.3.4)
cliver (0.3.2)
coderay (1.1.0)
@@ -673,9 +672,6 @@ GEM
tilt (>= 1.3, < 3)
six (0.2.0)
slack-notifier (1.2.1)
- slim (2.0.3)
- temple (~> 0.6.6)
- tilt (>= 1.3.3, < 2.1)
slop (3.6.0)
spinach (0.8.10)
colorize
@@ -711,7 +707,6 @@ GEM
railties (>= 3.2.5, < 5)
teaspoon-jasmine (2.2.0)
teaspoon (>= 1.0.0)
- temple (0.6.10)
term-ansicolor (1.3.2)
tins (~> 1.0)
terminal-table (1.5.2)
@@ -776,9 +771,6 @@ GEM
websocket-driver (0.6.2)
websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.2)
- whenever (0.8.4)
- activesupport (>= 2.3.4)
- chronic (>= 0.6.3)
wikicloth (0.8.1)
builder
expression_parser
@@ -919,7 +911,6 @@ DEPENDENCIES
sinatra (~> 1.4.4)
six (~> 0.2.0)
slack-notifier (~> 1.2.0)
- slim (~> 2.0.2)
spinach-rails (~> 0.2.1)
spring (~> 1.3.6)
spring-commands-rspec (~> 1.0.4)
@@ -943,7 +934,6 @@ DEPENDENCIES
version_sorter (~> 2.0.0)
virtus (~> 1.0.1)
webmock (~> 1.21.0)
- whenever (~> 0.8.4)
wikicloth (= 0.8.1)
BUNDLED WITH
diff --git a/PROCESS.md b/PROCESS.md
index 1b6b3e7d32d..9f4b708d2b5 100644
--- a/PROCESS.md
+++ b/PROCESS.md
@@ -79,7 +79,11 @@ Thanks for the issue report but we only support issues for the latest stable ver
### Support requests and configuration questions
-Thanks for your interest in GitLab. We don't use the issue tracker for support requests and configuration questions. Please use the \[support forum\]\(https://groups.google.com/forum/#!forum/gitlabhq), \[Stack Overflow\]\(http://stackoverflow.com/questions/tagged/gitlab), the #gitlab IRC channel on Freenode or the http://about.gitlab.com paid services for this purpose. Have a look at the \[contribution guidelines\]\(https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CONTRIBUTING.md) for more information.
+Thanks for your interest in GitLab. We don't use the issue tracker for support
+requests and configuration questions. Please check our
+\[getting help\]\(https://about.gitlab.com/getting-help/) page to see all of the available
+support options. Also, have a look at the \[contribution guidelines\]\(https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CONTRIBUTING.md)
+for more information.
### Code format
diff --git a/app/assets/javascripts/application.js.coffee b/app/assets/javascripts/application.js.coffee
index 8e987ac4e83..945ffb660e6 100644
--- a/app/assets/javascripts/application.js.coffee
+++ b/app/assets/javascripts/application.js.coffee
@@ -180,6 +180,7 @@ $ ->
$('.navbar-toggle').on 'click', ->
$('.header-content .title').toggle()
$('.header-content .navbar-collapse').toggle()
+ $('.navbar-toggle').toggleClass('active')
# Show/hide comments on diff
$("body").on "click", ".js-toggle-diff-comments", (e) ->
diff --git a/app/assets/javascripts/merge_request_tabs.js.coffee b/app/assets/javascripts/merge_request_tabs.js.coffee
index 4e56791bde4..3e77ea515f8 100644
--- a/app/assets/javascripts/merge_request_tabs.js.coffee
+++ b/app/assets/javascripts/merge_request_tabs.js.coffee
@@ -69,7 +69,7 @@ class @MergeRequestTabs
scrollToElement: (container) ->
if window.location.hash
top = $(container + " " + window.location.hash).offset().top
- $('body').scrollTo(top);
+ $('body').scrollTo(top)
# Activate a tab based on the current action
activateTab: (action) ->
@@ -139,13 +139,16 @@ class @MergeRequestTabs
@diffsLoaded = true
@scrollToElement(".diffs")
- toggleLoading: ->
- $('.mr-loading-status .loading').toggle()
+ # Show or hide the loading spinner
+ #
+ # status - Boolean, true to show, false to hide
+ toggleLoading: (status) ->
+ $('.mr-loading-status .loading').toggle(status)
_get: (options) ->
defaults = {
- beforeSend: @toggleLoading
- complete: @toggleLoading
+ beforeSend: => @toggleLoading(true)
+ complete: => @toggleLoading(false)
dataType: 'json'
type: 'GET'
}
diff --git a/app/assets/stylesheets/generic/header.scss b/app/assets/stylesheets/generic/header.scss
index 543ce41ab52..91e6975e269 100644
--- a/app/assets/stylesheets/generic/header.scss
+++ b/app/assets/stylesheets/generic/header.scss
@@ -50,15 +50,17 @@ header {
.navbar-toggle {
color: #666;
- margin: 0;
+ margin: 6px 0;
border-radius: 0;
position: absolute;
right: 2px;
- top: 15px;
&:hover {
background-color: #EEE;
}
+ &.active {
+ color: #7f8fa4;
+ }
}
}
}
@@ -87,6 +89,7 @@ header {
.navbar-collapse {
float: right;
+ border-top: none;
}
}
diff --git a/app/assets/stylesheets/pages/diff.scss b/app/assets/stylesheets/pages/diff.scss
index 5e7e59a6af8..d9ef06dc6b6 100644
--- a/app/assets/stylesheets/pages/diff.scss
+++ b/app/assets/stylesheets/pages/diff.scss
@@ -1,3 +1,4 @@
+// Common
.diff-file {
margin-left: -$gl-padding;
margin-right: -$gl-padding;
@@ -12,24 +13,17 @@
color: #555;
z-index: 10;
- > span {
+ .diff-title {
font-family: $monospace_font;
word-break: break-all;
- margin-right: 200px;
display: block;
.file-mode {
- margin-left: 10px;
color: #777;
}
}
- .diff-btn-group {
- float: right;
- position: absolute;
- top: 5px;
- right: 15px;
-
+ .diff-controls {
.btn {
padding: 0px 10px;
font-size: 13px;
@@ -90,12 +84,12 @@
}
}
- tr.line_holder.parallel{
+ tr.line_holder.parallel {
.old_line, .new_line, .diff_line {
min-width: 50px;
}
- td.line_content.parallel{
+ td.line_content.parallel {
width: 50%;
}
}
@@ -105,7 +99,7 @@
padding: 0px;
border: none;
background: $background-color;
- color: rgba(0,0,0,0.3);
+ color: rgba(0, 0, 0, 0.3);
padding: 0px 5px;
border-right: 1px solid $border-color;
text-align: right;
@@ -117,7 +111,7 @@
float: left;
width: 35px;
font-weight: normal;
- color: rgba(0,0,0,0.3);
+ color: rgba(0, 0, 0, 0.3);
&:hover {
text-decoration: underline;
}
@@ -168,7 +162,7 @@
background: #ddd;
text-align: center;
padding: 30px;
- .wrap{
+ .wrap {
display: inline-block;
}
@@ -176,7 +170,7 @@
display: inline-block;
background-color: #fff;
line-height: 0;
- img{
+ img {
border: 1px solid #FFF;
background: image-url('trans_bg.gif');
max-width: 100%;
@@ -189,21 +183,21 @@
border: 1px solid $added;
}
}
- .image-info{
+ .image-info {
font-size: 12px;
margin: 5px 0 0 0;
color: grey;
}
- .view.swipe{
+ .view.swipe {
position: relative;
- .swipe-frame{
+ .swipe-frame {
display: block;
margin: auto;
position: relative;
}
- .swipe-wrap{
+ .swipe-wrap {
overflow: hidden;
border-left: 1px solid #999;
position: absolute;
@@ -211,33 +205,33 @@
top: 13px;
right: 7px;
}
- .frame{
+ .frame {
top: 0;
right: 0;
position: absolute;
- &.deleted{
+ &.deleted {
margin: 0;
display: block;
top: 13px;
right: 7px;
}
}
- .swipe-bar{
+ .swipe-bar {
display: block;
height: 100%;
width: 15px;
z-index: 100;
position: absolute;
cursor: pointer;
- &:hover{
- .top-handle{
+ &:hover {
+ .top-handle {
background-position: -15px 3px;
}
- .bottom-handle{
+ .bottom-handle {
background-position: -15px -11px;
}
- };
- .top-handle{
+ }
+ .top-handle {
display: block;
height: 14px;
width: 15px;
@@ -245,7 +239,7 @@
top: 0px;
background: image-url('swipemode_sprites.gif') 0 3px no-repeat;
}
- .bottom-handle{
+ .bottom-handle {
display: block;
height: 14px;
width: 15px;
@@ -254,9 +248,10 @@
background: image-url('swipemode_sprites.gif') 0 -11px no-repeat;
}
}
- } //.view.swipe
- .view.onion-skin{
- .onion-skin-frame{
+ }
+ //.view.swipe
+ .view.onion-skin {
+ .onion-skin-frame {
display: block;
margin: auto;
position: relative;
@@ -267,7 +262,7 @@
top: 0px;
left: 0px;
}
- .controls{
+ .controls {
display: block;
height: 14px;
width: 300px;
@@ -277,7 +272,7 @@
left: 50%;
margin-left: -150px;
- .drag-track{
+ .drag-track {
display: block;
position: absolute;
left: 12px;
@@ -317,39 +312,40 @@
background: image-url('onion_skin_sprites.gif') -2px -10px no-repeat;
}
}
- } //.view.onion-skin
+ }
+ //.view.onion-skin
}
- .view-modes{
+ .view-modes {
padding: 10px;
text-align: center;
background: #EEE;
- ul, li{
+ ul, li {
list-style: none;
margin: 0;
padding: 0;
display: inline-block;
}
- li{
+ li {
color: grey;
border-left: 1px solid #c1c1c1;
padding: 0 12px 0 16px;
cursor: pointer;
- &:first-child{
+ &:first-child {
border-left: none;
}
- &:hover{
+ &:hover {
text-decoration: underline;
}
- &.active{
- &:hover{
+ &.active {
+ &:hover {
text-decoration: none;
}
cursor: default;
color: #333;
}
- &.disabled{
+ &.disabled {
display: none;
}
}
@@ -373,3 +369,37 @@
float: right;
margin-top: -5px;
}
+
+// Mobile
+@media (max-width: 480px) {
+ .diff-title {
+ margin: 0;
+
+ .file-mode {
+ display: none;
+ }
+ }
+
+ .diff-controls {
+ position: static;
+ text-align: center;
+ }
+}
+
+// Bigger screens
+@media (min-width: 481px) {
+ .diff-title {
+ margin-right: 200px;
+
+ .file-mode {
+ margin-left: 10px;
+ }
+ }
+
+ .diff-controls {
+ float: right;
+ position: absolute;
+ top: 5px;
+ right: 15px;
+ }
+}
diff --git a/app/assets/stylesheets/pages/merge_requests.scss b/app/assets/stylesheets/pages/merge_requests.scss
index fe69d16fc4b..a1a5208c59c 100644
--- a/app/assets/stylesheets/pages/merge_requests.scss
+++ b/app/assets/stylesheets/pages/merge_requests.scss
@@ -75,7 +75,7 @@
.mr-widget-footer {
padding: 15px;
}
-
+
.normal {
color: #5c5d5e;
}
@@ -102,7 +102,7 @@
}
}
-.merge-request .merge-request-tabs{
+.merge-request .merge-request-tabs {
@include nav-menu;
margin: -$gl-padding;
padding: $gl-padding;
@@ -110,6 +110,20 @@
margin-bottom: 1px;
}
+// Mobile
+@media (max-width: 480px) {
+ .merge-request .merge-request-tabs {
+ margin: 0;
+ padding: 0;
+
+ li {
+ a {
+ padding: 0;
+ }
+ }
+ }
+}
+
.mr_source_commit,
.mr_target_commit {
.commit {
diff --git a/app/helpers/labels_helper.rb b/app/helpers/labels_helper.rb
index 662ace367b9..66b18eea699 100644
--- a/app/helpers/labels_helper.rb
+++ b/app/helpers/labels_helper.rb
@@ -95,7 +95,8 @@ module LabelsHelper
def project_labels_options(project)
labels = project.labels.to_a
labels.unshift(Label::None)
- options_from_collection_for_select(labels, 'name', 'name', params[:label_name])
+ labels.unshift(Label::Any)
+ options_from_collection_for_select(labels, 'name', 'title', params[:label_name])
end
# Required for Gitlab::Markdown::LabelReferenceFilter
diff --git a/app/helpers/milestones_helper.rb b/app/helpers/milestones_helper.rb
index 132a893e532..37a5b58cce8 100644
--- a/app/helpers/milestones_helper.rb
+++ b/app/helpers/milestones_helper.rb
@@ -30,7 +30,8 @@ module MilestonesHelper
grouped_milestones = Milestones::GroupService.new(milestones).execute
grouped_milestones.unshift(Milestone::None)
+ grouped_milestones.unshift(Milestone::Any)
- options_from_collection_for_select(grouped_milestones, 'title', 'title', params[:milestone_title])
+ options_from_collection_for_select(grouped_milestones, 'name', 'title', params[:milestone_title])
end
end
diff --git a/app/models/group_milestone.rb b/app/models/group_milestone.rb
index ab055f6b80b..1dd2be68ebf 100644
--- a/app/models/group_milestone.rb
+++ b/app/models/group_milestone.rb
@@ -1,5 +1,7 @@
class GroupMilestone
+ alias_attribute :name, :title
+
def initialize(title, milestones)
@title = title
@milestones = milestones
diff --git a/app/models/label.rb b/app/models/label.rb
index 14b544b3756..1bb4b5f55cf 100644
--- a/app/models/label.rb
+++ b/app/models/label.rb
@@ -14,7 +14,9 @@ class Label < ActiveRecord::Base
include Referable
# Represents a "No Label" state used for filtering Issues and Merge
# Requests that have no label assigned.
- None = Struct.new(:title, :name).new('No Label', 'No Label')
+ LabelStruct = Struct.new(:title, :name)
+ None = LabelStruct.new('No Label', 'No Label')
+ Any = LabelStruct.new('Any', '')
DEFAULT_COLOR = '#428BCA'
diff --git a/app/models/milestone.rb b/app/models/milestone.rb
index d979a35084b..84acba30b6b 100644
--- a/app/models/milestone.rb
+++ b/app/models/milestone.rb
@@ -16,7 +16,9 @@
class Milestone < ActiveRecord::Base
# Represents a "No Milestone" state used for filtering Issues and Merge
# Requests that have no milestone assigned.
- None = Struct.new(:title).new('No Milestone')
+ MilestoneStruct = Struct.new(:title, :name)
+ None = MilestoneStruct.new('No Milestone', 'No Milestone')
+ Any = MilestoneStruct.new('Any', '')
include InternalId
include Sortable
@@ -47,6 +49,8 @@ class Milestone < ActiveRecord::Base
state :active
end
+ alias_attribute :name, :title
+
class << self
def search(query)
query = "%#{query}%"
diff --git a/app/views/admin/users/index.html.haml b/app/views/admin/users/index.html.haml
index e3698ac1c46..97e4bb2fd73 100644
--- a/app/views/admin/users/index.html.haml
+++ b/app/views/admin/users/index.html.haml
@@ -54,19 +54,19 @@
%b.caret
%ul.dropdown-menu
%li
- = link_to admin_users_path(sort: sort_value_name) do
+ = link_to admin_users_path(sort: sort_value_name, filter: params[:filter]) do
= sort_title_name
- = link_to admin_users_path(sort: sort_value_recently_signin) do
+ = link_to admin_users_path(sort: sort_value_recently_signin, filter: params[:filter]) do
= sort_title_recently_signin
- = link_to admin_users_path(sort: sort_value_oldest_signin) do
+ = link_to admin_users_path(sort: sort_value_oldest_signin, filter: params[:filter]) do
= sort_title_oldest_signin
- = link_to admin_users_path(sort: sort_value_recently_created) do
+ = link_to admin_users_path(sort: sort_value_recently_created, filter: params[:filter]) do
= sort_title_recently_created
- = link_to admin_users_path(sort: sort_value_oldest_created) do
+ = link_to admin_users_path(sort: sort_value_oldest_created, filter: params[:filter]) do
= sort_title_oldest_created
- = link_to admin_users_path(sort: sort_value_recently_updated) do
+ = link_to admin_users_path(sort: sort_value_recently_updated, filter: params[:filter]) do
= sort_title_recently_updated
- = link_to admin_users_path(sort: sort_value_oldest_updated) do
+ = link_to admin_users_path(sort: sort_value_oldest_updated, filter: params[:filter]) do
= sort_title_oldest_updated
= link_to 'New User', new_admin_user_path, class: "btn btn-new btn-sm"
diff --git a/app/views/profiles/keys/_key_details.html.haml b/app/views/profiles/keys/_key_details.html.haml
index e0ae4d9720f..0ca8bd95157 100644
--- a/app/views/profiles/keys/_key_details.html.haml
+++ b/app/views/profiles/keys/_key_details.html.haml
@@ -18,5 +18,6 @@
%code.key-fingerprint= @key.fingerprint
%pre.well-pre
= @key.key
- .pull-right
- = link_to 'Remove', path_to_key(@key, is_admin), data: {confirm: 'Are you sure?'}, method: :delete, class: "btn btn-remove delete-key"
+ .col-md-12
+ .pull-right
+ = link_to 'Remove', path_to_key(@key, is_admin), data: {confirm: 'Are you sure?'}, method: :delete, class: "btn btn-remove delete-key"
diff --git a/app/views/projects/diffs/_file.html.haml b/app/views/projects/diffs/_file.html.haml
index 4617b188150..9698921f6da 100644
--- a/app/views/projects/diffs/_file.html.haml
+++ b/app/views/projects/diffs/_file.html.haml
@@ -16,7 +16,7 @@
- if diff_file.mode_changed?
%span.file-mode= "#{diff_file.diff.a_mode} → #{diff_file.diff.b_mode}"
- .diff-btn-group
+ .diff-controls
- if blob.text?
= link_to '#', class: 'js-toggle-diff-comments btn btn-sm active has_tooltip', title: "Toggle comments for this file" do
%i.fa.fa-comments
diff --git a/app/views/projects/forks/new.html.haml b/app/views/projects/forks/new.html.haml
index cd5f3a5d39e..f0b0a11c04a 100644
--- a/app/views/projects/forks/new.html.haml
+++ b/app/views/projects/forks/new.html.haml
@@ -1,36 +1,41 @@
- page_title "Fork project"
-%h3.page-title Fork project
-%p.lead
- Click to fork the project to a user or group
-%hr
+- if @namespaces.present?
+ %h3.page-title Fork project
+ %p.lead
+ Click to fork the project to a user or group
+ %hr
-.fork-namespaces
- - @namespaces.in_groups_of(6, false) do |group|
- .row
- - group.each do |namespace|
- .col-md-2.col-sm-3
- - if fork = namespace.find_fork_of(@project)
- .fork-thumbnail
- = link_to project_path(fork), title: "Visit project fork", class: 'has_tooltip' do
- = image_tag namespace_icon(namespace, 100)
- .caption
- %strong
- = namespace.human_name
- %div.text-primary
- Already forked
+ .fork-namespaces
+ - @namespaces.in_groups_of(6, false) do |group|
+ .row
+ - group.each do |namespace|
+ .col-md-2.col-sm-3
+ - if fork = namespace.find_fork_of(@project)
+ .fork-thumbnail
+ = link_to project_path(fork), title: "Visit project fork", class: 'has_tooltip' do
+ = image_tag namespace_icon(namespace, 100)
+ .caption
+ %strong
+ = namespace.human_name
+ %div.text-primary
+ Already forked
- - else
- .fork-thumbnail
- = link_to namespace_project_fork_path(@project.namespace, @project, namespace_key: namespace.id), title: "Fork here", method: "POST", class: 'has_tooltip' do
- = image_tag namespace_icon(namespace, 100)
- .caption
- %strong
- = namespace.human_name
+ - else
+ .fork-thumbnail
+ = link_to namespace_project_fork_path(@project.namespace, @project, namespace_key: namespace.id), title: "Fork here", method: "POST", class: 'has_tooltip' do
+ = image_tag namespace_icon(namespace, 100)
+ .caption
+ %strong
+ = namespace.human_name
- %p.light
- Fork is a copy of a project repository.
- %br
- Forking a repository allows you to do changes without affecting the original project.
+ %p.light
+ Fork is a copy of a project repository.
+ %br
+ Forking a repository allows you to do changes without affecting the original project.
+- else
+ %h3 No available namespaces to fork the project
+ %p.slead
+ You must have permission to create a project in a namespace before forking.
.save-project-loader.hide
.center
diff --git a/app/views/shared/issuable/_filter.html.haml b/app/views/shared/issuable/_filter.html.haml
index 6e6d497c1d2..8f16773077e 100644
--- a/app/views/shared/issuable/_filter.html.haml
+++ b/app/views/shared/issuable/_filter.html.haml
@@ -39,13 +39,13 @@
.filter-item.inline.milestone-filter
= select_tag('milestone_title', projects_milestones_options,
- class: 'select2 trigger-submit', include_blank: 'Any',
+ class: 'select2 trigger-submit', include_blank: true,
data: {placeholder: 'Milestone'})
- if @project
.filter-item.inline.labels-filter
= select_tag('label_name', project_labels_options(@project),
- class: 'select2 trigger-submit', include_blank: 'Any',
+ class: 'select2 trigger-submit', include_blank: true,
data: {placeholder: 'Label'})
.pull-right
diff --git a/doc/raketasks/user_management.md b/doc/raketasks/user_management.md
index 4fbd20762da..629d38efc53 100644
--- a/doc/raketasks/user_management.md
+++ b/doc/raketasks/user_management.md
@@ -56,3 +56,17 @@ bundle exec rake gitlab:import:all_users_to_all_groups RAILS_ENV=production
```
block_auto_created_users: false
```
+
+## Disable Two-factor Authentication (2FA) for all users
+
+This task will disable 2FA for all users that have it enabled. This can be
+useful if GitLab's `.secret` file has been lost and users are unable to login,
+for example.
+
+```bash
+# omnibus-gitlab
+sudo gitlab-rake gitlab:two_factor:disable_for_all_users
+
+# installation from source
+bundle exec rake gitlab:two_factor:disable_for_all_users RAILS_ENV=production
+```
diff --git a/doc/release/monthly.md b/doc/release/monthly.md
index c56e99a7005..bd8a67d1d85 100644
--- a/doc/release/monthly.md
+++ b/doc/release/monthly.md
@@ -74,20 +74,19 @@ Xth: (1 working day before the 22nd)
- [ ] Update GitLab.com with the latest RC (#LINK)
- [ ] Update ci.gitLab.com with the latest RC (#LINK)
-22nd before 12AM CET:
+22nd before 1200 CET:
-Release before 12AM CET / 3AM PST, to make sure the majority of our users
+Release before 1200 CET / 2AM PST, to make sure the majority of our users
get the new version on the 22nd and there is sufficient time in the European
workday to quickly fix any issues.
- [ ] Merge CE stable into EE stable (#LINK)
- [ ] Create the 'x.y.0' tag with the [release tools](https://dev.gitlab.org/gitlab/release-tools) (#LINK)
- [ ] Create the 'x.y.0' version on version.gitlab.com
-- [ ] Try to do before 11AM CET: Create and push omnibus tags for x.y.0 (will auto-release the packages) (#LINK)
-- [ ] Try to do before 12AM CET: Publish the release blog post (#LINK)
+- [ ] Try to do before 1100 CET: Create and push omnibus tags for x.y.0 (will auto-release the packages) (#LINK)
+- [ ] Try to do before 1200 CET: Publish the release blog post (#LINK)
- [ ] Tweet about the release (blog post) (#LINK)
-- [ ] Schedule a second tweet of the release announcement with the same text at 6PM CET / 9AM PST
-
+- [ ] Schedule a second tweet of the release announcement with the same text at 1800 CET / 8AM PST
```
- - -
@@ -223,4 +222,4 @@ Consider creating a post on Hacker News.
## Create a WIP blogpost for the next release
-Create a WIP blogpost using [release blog template](https://gitlab.com/gitlab-com/www-gitlab-com/blob/master/doc/release_blog_template.md). \ No newline at end of file
+Create a WIP blogpost using [release blog template](https://gitlab.com/gitlab-com/www-gitlab-com/blob/master/doc/release_blog_template.md).
diff --git a/lib/gitlab/backend/shell.rb b/lib/gitlab/backend/shell.rb
index 14ee4701e7b..01b8bda05c6 100644
--- a/lib/gitlab/backend/shell.rb
+++ b/lib/gitlab/backend/shell.rb
@@ -4,7 +4,8 @@ module Gitlab
class KeyAdder < Struct.new(:io)
def add_key(id, key)
- io.puts("#{id}\t#{key.strip}")
+ key.gsub!(/[[:space:]]+/, ' ').strip!
+ io.puts("#{id}\t#{key}")
end
end
diff --git a/lib/tasks/gitlab/two_factor.rake b/lib/tasks/gitlab/two_factor.rake
new file mode 100644
index 00000000000..9196677a017
--- /dev/null
+++ b/lib/tasks/gitlab/two_factor.rake
@@ -0,0 +1,23 @@
+namespace :gitlab do
+ namespace :two_factor do
+ desc "GitLab | Disable Two-factor authentication (2FA) for all users"
+ task disable_for_all_users: :environment do
+ scope = User.with_two_factor
+ count = scope.count
+
+ if count > 0
+ puts "This will disable 2FA for #{count.to_s.red} users..."
+
+ begin
+ ask_to_continue
+ scope.find_each(&:disable_two_factor!)
+ puts "Successfully disabled 2FA for #{count} users.".green
+ rescue Gitlab::TaskAbortedByUserError
+ puts "Quitting...".red
+ end
+ else
+ puts "There are currently no users with 2FA enabled.".yellow
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/backend/shell_spec.rb b/spec/lib/gitlab/backend/shell_spec.rb
index b6d04330599..b60e23454d6 100644
--- a/spec/lib/gitlab/backend/shell_spec.rb
+++ b/spec/lib/gitlab/backend/shell_spec.rb
@@ -15,4 +15,17 @@ describe Gitlab::Shell do
it { is_expected.to respond_to :fork_repository }
it { expect(gitlab_shell.url_to_repo('diaspora')).to eq(Gitlab.config.gitlab_shell.ssh_path_prefix + "diaspora.git") }
+
+ describe Gitlab::Shell::KeyAdder do
+ describe '#add_key' do
+ it 'normalizes space characters in the key' do
+ io = spy
+ adder = described_class.new(io)
+
+ adder.add_key('key-42', "sha-rsa foo\tbar\tbaz")
+
+ expect(io).to have_received(:puts).with("key-42\tsha-rsa foo bar baz")
+ end
+ end
+ end
end