diff options
80 files changed, 511 insertions, 292 deletions
diff --git a/.gitignore b/.gitignore index aff8ad9ecbe..39caad149b3 100644 --- a/.gitignore +++ b/.gitignore @@ -21,7 +21,6 @@ config/aws.yml config/database.yml config/gitlab.yml config/gitlab_ci.yml -config/initializers/omniauth.rb config/initializers/rack_attack.rb config/initializers/smtp_settings.rb config/resque.yml diff --git a/CHANGELOG b/CHANGELOG index 67ded53ad79..6ed1716f8af 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,7 +1,9 @@ Please view this file on the master branch, on stable branches it's out of date. v 8.0.0 (unreleased) - - Fix Error 500 in API when accessing a group that has an avatar (Stan Hu) + - Prevent too many redirects upon login when home page URL is set to external_url (Stan Hu) + - Improve dropdown positioning on the project home page (Hannes Rosenögger) + - Upgrade browser gem to 1.0.0 to avoid warning in IE11 compatibilty mode (Stan Hu) - Remove user OAuth tokens from the database and request new tokens each session (Stan Hu) - Only show recent push event if the branch still exists or a recent merge request has not been created (Stan Hu) - Remove satellites @@ -13,6 +15,17 @@ v 8.0.0 (unreleased) - Search for comments should be case insensetive - Create cross-reference for closing references on commits pushed to non-default branches (Maël Valais) - Ability to search milestones + - Gracefully handle SMTP user input errors (e.g. incorrect email addresses) to prevent Sidekiq retries (Stan Hu) + - Move dashboard activity to separate page + - Improve performance of git blame + - Limit content width to 1200px for most of pages to improve readability on big screens + +v 7.14.1 + - Improve abuse reports management from admin area + - Fix "Reload with full diff" URL button in compare branch view (Stan Hu) + - Only include base URL in OmniAuth full_host parameter (Stan Hu) + - Fix Error 500 in API when accessing a group that has an avatar (Stan Hu) + - Ability to enable SSL verification for Webhooks v 7.14.0 - Fix bug where non-project members of the target project could set labels on new merge requests. @@ -298,6 +311,7 @@ v 7.11.0 - Protect OmniAuth request phase against CSRF. - Don't send notifications to mentioned users that don't have access to the project in question. - Add search issues/MR by number + - Change plots to bar graphs in commit statistics screen - Move snippets UI to fluid layout - Improve UI for sidebar. Increase separation between navigation and content - Improve new project command options (Ben Bodenmiller) @@ -42,7 +42,7 @@ gem 'rqrcode-rails3', '~> 0.1.7' gem 'attr_encrypted', '~> 1.3.4' # Browser detection -gem "browser", '~> 0.8.0' +gem "browser", '~> 1.0.0' # Extracting information from a git repository # Provide access to Gitlab::Git library @@ -285,7 +285,7 @@ gem "newrelic_rpm", '~> 3.9.4.245' gem 'octokit', '~> 3.7.0' -gem "mail_room", "~> 0.4.0" +gem "mail_room", "~> 0.4.1" gem 'email_reply_parser', '~> 0.5.8' diff --git a/Gemfile.lock b/Gemfile.lock index b810f2fdd4e..97e4c258615 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -82,7 +82,7 @@ GEM ruby_parser (~> 3.7.0) sass (~> 3.0) terminal-table (~> 1.4) - browser (0.8.0) + browser (1.0.0) builder (3.2.2) byebug (6.0.2) cal-heatmap-rails (0.0.1) @@ -388,7 +388,7 @@ GEM systemu (~> 2.6.2) mail (2.6.3) mime-types (>= 1.16, < 3) - mail_room (0.4.0) + mail_room (0.4.1) method_source (0.8.2) mime-types (1.25.1) mimemagic (0.3.0) @@ -790,7 +790,7 @@ DEPENDENCIES binding_of_caller (~> 0.7.2) bootstrap-sass (~> 3.0) brakeman - browser (~> 0.8.0) + browser (~> 1.0.0) byebug cal-heatmap-rails (~> 0.0.1) capybara (~> 2.4.0) @@ -846,7 +846,7 @@ DEPENDENCIES jquery-ui-rails (~> 4.2.1) kaminari (~> 0.15.1) letter_opener (~> 1.1.2) - mail_room (~> 0.4.0) + mail_room (~> 0.4.1) minitest (~> 5.7.0) mousetrap-rails (~> 1.4.6) mysql2 (~> 0.3.16) diff --git a/app/assets/javascripts/application.js.coffee b/app/assets/javascripts/application.js.coffee index bb0a0c51fd4..c263912b7ea 100644 --- a/app/assets/javascripts/application.js.coffee +++ b/app/assets/javascripts/application.js.coffee @@ -116,6 +116,12 @@ $ -> $('.remove-row').bind 'ajax:success', -> $(this).closest('li').fadeOut() + $('.js-remove-tr').bind 'ajax:before', -> + $(this).hide() + + $('.js-remove-tr').bind 'ajax:success', -> + $(this).closest('tr').fadeOut() + # Initialize select2 selects $('select.select2').select2(width: 'resolve', dropdownAutoWidth: true) diff --git a/app/assets/javascripts/dispatcher.js.coffee b/app/assets/javascripts/dispatcher.js.coffee index 81e73799271..539041c2862 100644 --- a/app/assets/javascripts/dispatcher.js.coffee +++ b/app/assets/javascripts/dispatcher.js.coffee @@ -51,6 +51,7 @@ class Dispatcher MergeRequests.init() when 'dashboard:show', 'root:show' new Dashboard() + when 'dashboard:activity' new Activities() when 'dashboard:projects:starred' new Activities() diff --git a/app/assets/javascripts/projects_list.js.coffee b/app/assets/javascripts/projects_list.js.coffee index c0e36d1ccc5..db5faf71faf 100644 --- a/app/assets/javascripts/projects_list.js.coffee +++ b/app/assets/javascripts/projects_list.js.coffee @@ -8,7 +8,7 @@ class @ProjectsList $(".projects-list-filter").keyup -> terms = $(this).val() - uiBox = $(this).closest('.panel') + uiBox = $(this).closest('.projects-list-holder') if terms == "" || terms == undefined uiBox.find(".projects-list li").show() else diff --git a/app/assets/stylesheets/base/layout.scss b/app/assets/stylesheets/base/layout.scss index 690d89a5c16..734b95e26c0 100644 --- a/app/assets/stylesheets/base/layout.scss +++ b/app/assets/stylesheets/base/layout.scss @@ -20,3 +20,8 @@ html { .navless-container { margin-top: 30px; } + + +.container-limited { + max-width: $fixed-layout-width; +} diff --git a/app/assets/stylesheets/base/variables.scss b/app/assets/stylesheets/base/variables.scss index cb439a0e0bf..26d0a1e5363 100644 --- a/app/assets/stylesheets/base/variables.scss +++ b/app/assets/stylesheets/base/variables.scss @@ -13,7 +13,7 @@ $code_line_height: 1.5; $border-color: #E5E5E5; $background-color: #f5f5f5; $header-height: 50px; -$readable-width: 1100px; +$fixed-layout-width: 1200px; /* diff --git a/app/assets/stylesheets/generic/header.scss b/app/assets/stylesheets/generic/header.scss index 31e2ad86691..6a29b32e196 100644 --- a/app/assets/stylesheets/generic/header.scss +++ b/app/assets/stylesheets/generic/header.scss @@ -20,16 +20,16 @@ header { } &.navbar-gitlab { + padding: 0 20px; z-index: 100; margin-bottom: 0; min-height: $header-height; border: none; - width: 100%; + border-bottom: 1px solid #EEE; - .container { + .container-fluid { background: #FFF; width: 100% !important; - padding: 0; filter: none; .nav > li > a { @@ -64,55 +64,11 @@ header { } } - .header-logo { - border-bottom: 1px solid transparent; - float: left; - height: $header-height; - width: $sidebar_width; - overflow: hidden; - transition-duration: .3s; - - a { - float: left; - height: $header-height; - width: 100%; - padding: ($header-height - 36 ) / 2 8px; - overflow: hidden; - - img { - width: 36px; - height: 36px; - float: left; - } - - .gitlab-text-container { - width: 230px; - - h3 { - width: 158px; - float: left; - margin: 0; - margin-left: 14px; - font-size: 18px; - line-height: $header-height - 14; - font-weight: normal; - } - } - } - - &:hover { - background-color: #EEE; - } - } - .header-content { - border-bottom: 1px solid #EEE; - padding-right: 35px; height: $header-height; .title { margin: 0; - padding: 0 15px 0 35px; overflow: hidden; font-size: 18px; line-height: $header-height; @@ -168,15 +124,7 @@ header { } @mixin collapsed-header { - .header-logo { - width: $sidebar_collapsed_width; - } - - .header-content { - .title { - margin-left: 30px; - } - } + margin-left: $sidebar_collapsed_width; } @media (max-width: $screen-md-max) { @@ -191,16 +139,14 @@ header { } .header-expanded { + margin-left: $sidebar_width; } } @media (max-width: $screen-xs-max) { - header .container { + header .container-fluid { font-size: 18px; - .title { - } - .navbar-nav { margin: 0px; float: none !important; diff --git a/app/assets/stylesheets/generic/sidebar.scss b/app/assets/stylesheets/generic/sidebar.scss index b96664d30db..320bdb1c765 100644 --- a/app/assets/stylesheets/generic/sidebar.scss +++ b/app/assets/stylesheets/generic/sidebar.scss @@ -188,3 +188,46 @@ width: $sidebar_width - 2 * 10px; } } + +.sidebar-wrapper { + .header-logo { + border-bottom: 1px solid transparent; + float: left; + height: $header-height; + width: $sidebar_width; + overflow: hidden; + transition-duration: .3s; + + a { + float: left; + height: $header-height; + width: 100%; + padding: ($header-height - 36 ) / 2 8px; + overflow: hidden; + + img { + width: 36px; + height: 36px; + float: left; + } + + .gitlab-text-container { + width: 230px; + + h3 { + width: 158px; + float: left; + margin: 0; + margin-left: 14px; + font-size: 18px; + line-height: $header-height - 14; + font-weight: normal; + } + } + } + + &:hover { + background-color: #EEE; + } + } +} diff --git a/app/assets/stylesheets/pages/dashboard.scss b/app/assets/stylesheets/pages/dashboard.scss index 9a3b543ad10..c1103a1c2e6 100644 --- a/app/assets/stylesheets/pages/dashboard.scss +++ b/app/assets/stylesheets/pages/dashboard.scss @@ -23,41 +23,6 @@ } } -.project-row, .group-row { - padding: 0 !important; - font-size: 14px; - line-height: 24px; - - a { - display: block; - padding: 8px 15px; - } - - .project-name, .group-name { - font-weight: 500; - } - - .arrow { - float: right; - margin: 0; - font-size: 20px; - } - - .last-activity { - float: right; - font-size: 12px; - color: #AAA; - display: block; - .date { - color: #777; - } - } -} - -.project-description { - overflow: hidden; -} - .project-access-icon { margin-left: 10px; float: left; @@ -73,10 +38,9 @@ float: left; .avatar { - margin-top: -8px; - margin-left: -15px; @include border-radius(0px); } + .identicon { line-height: 40px; } diff --git a/app/assets/stylesheets/pages/issuable.scss b/app/assets/stylesheets/pages/issuable.scss index 3f617e72b02..586e7b5f8da 100644 --- a/app/assets/stylesheets/pages/issuable.scss +++ b/app/assets/stylesheets/pages/issuable.scss @@ -45,9 +45,3 @@ .btn { font-size: 13px; } } - -.issuable-details { - .description { - max-width: $readable-width; - } -} diff --git a/app/assets/stylesheets/pages/projects.scss b/app/assets/stylesheets/pages/projects.scss index 29d3dbc25eb..4d065c3bdf6 100644 --- a/app/assets/stylesheets/pages/projects.scss +++ b/app/assets/stylesheets/pages/projects.scss @@ -30,14 +30,21 @@ } } + .project-home-dropdown { + margin: 11px 3px 0; + } + .project-home-desc { h1 { margin: 0; margin-bottom: 10px; font-size: 26px; + font-weight: bold; } p { + font-size: 18px; + color: #666; display: inline; } } @@ -316,3 +323,34 @@ table.table.protected-branches-list tr.no-border { pre.light-well { border-color: #f1f1f1; } + +.projects-search-form { + max-width: 600px; + margin: 0 auto; + margin-bottom: 20px; + + input { + border-color: #BBB; + } +} + +.project-row { + .project-full-name { + font-weight: bold; + font-size: 15px; + } + + .project-description { + color: #888; + font-size: 13px; + + p { + margin-bottom: 0; + color: #888; + } + } +} + +.my-projects .project-row { + padding: 10px 0; +} diff --git a/app/assets/stylesheets/pages/tree.scss b/app/assets/stylesheets/pages/tree.scss index 5f1a3db4fb6..81e2aa7bb9c 100644 --- a/app/assets/stylesheets/pages/tree.scss +++ b/app/assets/stylesheets/pages/tree.scss @@ -117,7 +117,6 @@ .readme-holder { margin: 0 auto; - max-width: $readable-width; .readme-file-title { font-size: 14px; diff --git a/app/assets/stylesheets/themes/gitlab-theme.scss b/app/assets/stylesheets/themes/gitlab-theme.scss index 3589cb88d03..77b62c3153f 100644 --- a/app/assets/stylesheets/themes/gitlab-theme.scss +++ b/app/assets/stylesheets/themes/gitlab-theme.scss @@ -7,27 +7,23 @@ * $color-dark - */ @mixin gitlab-theme($color-light, $color, $color-darker, $color-dark) { - header { - &.navbar-gitlab { - .header-logo { - background-color: $color-darker; - border-color: $color-darker; + .page-with-sidebar { + .header-logo { + background-color: $color-darker; + border-color: $color-darker; - a { - color: $color-light; - } + a { + color: $color-light; + } - &:hover { - background-color: $color-dark; - a { - color: #FFF; - } + &:hover { + background-color: $color-dark; + a { + color: #FFF; } } } - } - .page-with-sidebar { .collapse-nav a { color: #FFF; background: $color; diff --git a/app/controllers/admin/abuse_reports_controller.rb b/app/controllers/admin/abuse_reports_controller.rb index 34f37bca4ad..38a5a9fca08 100644 --- a/app/controllers/admin/abuse_reports_controller.rb +++ b/app/controllers/admin/abuse_reports_controller.rb @@ -4,8 +4,13 @@ class Admin::AbuseReportsController < Admin::ApplicationController end def destroy - AbuseReport.find(params[:id]).destroy + abuse_report = AbuseReport.find(params[:id]) - redirect_to admin_abuse_reports_path, notice: 'Report was removed' + if params[:remove_user] + abuse_report.user.destroy + end + + abuse_report.destroy + render nothing: true end end diff --git a/app/controllers/admin/hooks_controller.rb b/app/controllers/admin/hooks_controller.rb index 690096bdbcf..d670386f8c6 100644 --- a/app/controllers/admin/hooks_controller.rb +++ b/app/controllers/admin/hooks_controller.rb @@ -39,6 +39,6 @@ class Admin::HooksController < Admin::ApplicationController end def hook_params - params.require(:hook).permit(:url) + params.require(:hook).permit(:url, :enable_ssl_verification) end end diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index ac9484a4cd2..54d15b7d7c1 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -59,7 +59,9 @@ class ApplicationController < ActionController::Base def authenticate_user!(*args) # If user is not signed-in and tries to access root_path - redirect him to landing page - if current_application_settings.home_page_url.present? + # Don't redirect to the default URL to prevent endless redirections + if current_application_settings.home_page_url.present? && + current_application_settings.home_page_url.chomp('/') != Gitlab.config.gitlab['url'].chomp('/') if current_user.nil? && root_path == request.path redirect_to current_application_settings.home_page_url and return end diff --git a/app/controllers/dashboard_controller.rb b/app/controllers/dashboard_controller.rb index d2f0c43929f..d745131694b 100644 --- a/app/controllers/dashboard_controller.rb +++ b/app/controllers/dashboard_controller.rb @@ -1,6 +1,6 @@ class DashboardController < Dashboard::ApplicationController before_action :load_projects - before_action :event_filter, only: :show + before_action :event_filter, only: :activity respond_to :html @@ -10,13 +10,8 @@ class DashboardController < Dashboard::ApplicationController respond_to do |format| format.html - - format.json do - load_events - pager_json("events/_events", @events.count) - end - format.atom do + event_filter load_events render layout: false end @@ -40,6 +35,19 @@ class DashboardController < Dashboard::ApplicationController end end + def activity + @last_push = current_user.recent_push + + respond_to do |format| + format.html + + format.json do + load_events + pager_json("events/_events", @events.count) + end + end + end + protected def load_projects diff --git a/app/controllers/projects/hooks_controller.rb b/app/controllers/projects/hooks_controller.rb index 76062446c92..4e5b4125f5a 100644 --- a/app/controllers/projects/hooks_controller.rb +++ b/app/controllers/projects/hooks_controller.rb @@ -53,6 +53,7 @@ class Projects::HooksController < Projects::ApplicationController end def hook_params - params.require(:hook).permit(:url, :push_events, :issues_events, :merge_requests_events, :tag_push_events, :note_events) + params.require(:hook).permit(:url, :push_events, :issues_events, + :merge_requests_events, :tag_push_events, :note_events, :enable_ssl_verification) end end diff --git a/app/controllers/projects/services_controller.rb b/app/controllers/projects/services_controller.rb index 01105532479..b0cf5866d41 100644 --- a/app/controllers/projects/services_controller.rb +++ b/app/controllers/projects/services_controller.rb @@ -8,7 +8,7 @@ class Projects::ServicesController < Projects::ApplicationController :push_events, :issues_events, :merge_requests_events, :tag_push_events, :note_events, :send_from_committer_email, :disable_diffs, :external_wiki_url, :notify, :color, - :server_host, :server_port, :default_irc_uri] + :server_host, :server_port, :default_irc_uri, :enable_ssl_verification] # Authorize before_action :authorize_admin_project! before_action :service, only: [:edit, :update, :test] diff --git a/app/helpers/gitlab/page_layout_helper.rb b/app/helpers/gitlab/page_layout_helper.rb index d7a85186155..c89b2c2ba2c 100644 --- a/app/helpers/gitlab/page_layout_helper.rb +++ b/app/helpers/gitlab/page_layout_helper.rb @@ -24,5 +24,14 @@ module Gitlab @sidebar end end + + def fluid_layout(enabled = false) + if @fluid_layout.nil? + @fluid_layout = enabled + else + @fluid_layout + end + end end + end diff --git a/app/helpers/page_layout_helper.rb b/app/helpers/page_layout_helper.rb new file mode 100644 index 00000000000..8473d6d75d0 --- /dev/null +++ b/app/helpers/page_layout_helper.rb @@ -0,0 +1,34 @@ +module PageLayoutHelper + def page_title(*titles) + @page_title ||= [] + + @page_title.push(*titles.compact) if titles.any? + + @page_title.join(" | ") + end + + def header_title(title = nil, title_url = nil) + if title + @header_title = title + @header_title_url = title_url + else + @header_title_url ? link_to(@header_title, @header_title_url) : @header_title + end + end + + def sidebar(name = nil) + if name + @sidebar = name + else + @sidebar + end + end + + def fluid_layout(enabled = false) + if @fluid_layout.nil? + @fluid_layout = enabled + else + @fluid_layout + end + end +end diff --git a/app/mailers/email_rejection_mailer.rb b/app/mailers/email_rejection_mailer.rb index 89aceda82d1..883f1c73ad4 100644 --- a/app/mailers/email_rejection_mailer.rb +++ b/app/mailers/email_rejection_mailer.rb @@ -3,6 +3,8 @@ class EmailRejectionMailer < BaseMailer @reason = reason @original_message = Mail::Message.new(original_raw) + return unless @original_message.from + headers = { to: @original_message.from, subject: "[Rejected] #{@original_message.subject}" diff --git a/app/models/hooks/web_hook.rb b/app/models/hooks/web_hook.rb index 46fb85336e5..9a8251bdad5 100644 --- a/app/models/hooks/web_hook.rb +++ b/app/models/hooks/web_hook.rb @@ -25,6 +25,7 @@ class WebHook < ActiveRecord::Base default_value_for :note_events, false default_value_for :merge_requests_events, false default_value_for :tag_push_events, false + default_value_for :enable_ssl_verification, false # HTTParty timeout default_timeout Gitlab.config.gitlab.webhook_timeout @@ -41,7 +42,7 @@ class WebHook < ActiveRecord::Base "Content-Type" => "application/json", "X-Gitlab-Event" => hook_name.singularize.titleize }, - verify: false) + verify: enable_ssl_verification) else post_url = url.gsub("#{parsed_url.userinfo}@", "") auth = { @@ -54,7 +55,7 @@ class WebHook < ActiveRecord::Base "Content-Type" => "application/json", "X-Gitlab-Event" => hook_name.singularize.titleize }, - verify: false, + verify: enable_ssl_verification, basic_auth: auth) end rescue SocketError, Errno::ECONNRESET, Errno::ECONNREFUSED, Net::OpenTimeout => e diff --git a/app/models/project_services/buildkite_service.rb b/app/models/project_services/buildkite_service.rb index a714bc82246..9e5da6f45d2 100644 --- a/app/models/project_services/buildkite_service.rb +++ b/app/models/project_services/buildkite_service.rb @@ -23,7 +23,7 @@ require "addressable/uri" class BuildkiteService < CiService ENDPOINT = "https://buildkite.com" - prop_accessor :project_url, :token + prop_accessor :project_url, :token, :enable_ssl_verification validates :project_url, presence: true, if: :activated? validates :token, presence: true, if: :activated? @@ -37,6 +37,7 @@ class BuildkiteService < CiService def compose_service_hook hook = service_hook || build_service_hook hook.url = webhook_url + hook.enable_ssl_verification = enable_ssl_verification hook.save end @@ -96,7 +97,11 @@ class BuildkiteService < CiService { type: 'text', name: 'project_url', - placeholder: "#{ENDPOINT}/example/project" } + placeholder: "#{ENDPOINT}/example/project" }, + + { type: 'checkbox', + name: 'enable_ssl_verification', + title: "Enable SSL verification" } ] end diff --git a/app/models/project_services/gitlab_ci_service.rb b/app/models/project_services/gitlab_ci_service.rb index ecdcd48ae60..acbbc9935b6 100644 --- a/app/models/project_services/gitlab_ci_service.rb +++ b/app/models/project_services/gitlab_ci_service.rb @@ -21,7 +21,7 @@ class GitlabCiService < CiService API_PREFIX = "api/v1" - prop_accessor :project_url, :token + prop_accessor :project_url, :token, :enable_ssl_verification validates :project_url, presence: true, format: { with: /\A#{URI.regexp(%w(http https))}\z/, message: "should be a valid url" }, if: :activated? @@ -34,6 +34,7 @@ class GitlabCiService < CiService def compose_service_hook hook = service_hook || build_service_hook hook.url = [project_url, "/build", "?token=#{token}"].join("") + hook.enable_ssl_verification = enable_ssl_verification hook.save end @@ -136,7 +137,8 @@ class GitlabCiService < CiService def fields [ { type: 'text', name: 'token', placeholder: 'GitLab CI project specific token' }, - { type: 'text', name: 'project_url', placeholder: 'http://ci.gitlabhq.com/projects/3' } + { type: 'text', name: 'project_url', placeholder: 'http://ci.gitlabhq.com/projects/3' }, + { type: 'checkbox', name: 'enable_ssl_verification', title: "Enable SSL verification" } ] end diff --git a/app/views/admin/abuse_reports/_abuse_report.html.haml b/app/views/admin/abuse_reports/_abuse_report.html.haml index 4449721ae38..d3afc658cd6 100644 --- a/app/views/admin/abuse_reports/_abuse_report.html.haml +++ b/app/views/admin/abuse_reports/_abuse_report.html.haml @@ -3,7 +3,7 @@ %tr %td - if reporter - = link_to reporter.name, [:admin, reporter] + = link_to reporter.name, reporter - else (removed) %td @@ -12,12 +12,15 @@ = abuse_report.message %td - if user - = link_to user.name, [:admin, user] + = link_to user.name, user - else (removed) %td - if user - = link_to 'Block', block_admin_user_path(user), data: {confirm: 'USER WILL BE BLOCKED! Are you sure?'}, method: :put, class: "btn btn-xs btn-warning" - = link_to 'Remove user', [:admin, user], data: { confirm: "USER #{user.name} WILL BE REMOVED! Are you sure?" }, method: :delete, class: "btn btn-xs btn-remove" + = link_to 'Remove user & report', admin_abuse_report_path(abuse_report, remove_user: true), + data: { confirm: "USER #{user.name} WILL BE REMOVED! Are you sure?" }, remote: true, method: :delete, class: "btn btn-xs btn-remove js-remove-tr" + %td - = link_to 'Remove report', [:admin, abuse_report], method: :delete, class: "btn btn-xs btn-close" + - if user + = link_to 'Block user', block_admin_user_path(user), data: {confirm: 'USER WILL BE BLOCKED! Are you sure?'}, method: :put, class: "btn btn-xs" + = link_to 'Remove report', [:admin, abuse_report], remote: true, method: :delete, class: "btn btn-xs btn-close js-remove-tr" diff --git a/app/views/admin/abuse_reports/index.html.haml b/app/views/admin/abuse_reports/index.html.haml index 4a25848f156..2e8746146d1 100644 --- a/app/views/admin/abuse_reports/index.html.haml +++ b/app/views/admin/abuse_reports/index.html.haml @@ -9,7 +9,7 @@ %th Reported at %th Message %th User - %th + %th Primary action %th = render @abuse_reports = paginate @abuse_reports diff --git a/app/views/admin/hooks/index.html.haml b/app/views/admin/hooks/index.html.haml index e74e1e85f41..b120f4dea67 100644 --- a/app/views/admin/hooks/index.html.haml +++ b/app/views/admin/hooks/index.html.haml @@ -18,6 +18,13 @@ = f.label :url, "URL:", class: 'control-label' .col-sm-10 = f.text_field :url, class: "form-control" + .form-group + = f.label :enable_ssl_verification, "SSL verification", class: 'control-label checkbox' + .col-sm-10 + .checkbox + = f.label :enable_ssl_verification do + = f.check_box :enable_ssl_verification + %strong Enable SSL verification .form-actions = f.submit "Add System Hook", class: "btn btn-create" %hr @@ -32,6 +39,7 @@ .list-item-name = link_to admin_hook_path(hook) do %strong= hook.url + %p SSL Verification: #{hook.enable_ssl_verification ? "enabled" : "disabled"} .pull-right = link_to 'Test Hook', admin_hook_test_path(hook), class: "btn btn-sm" diff --git a/app/views/dashboard/_projects.html.haml b/app/views/dashboard/_projects.html.haml index d676576067c..dc83d5343f2 100644 --- a/app/views/dashboard/_projects.html.haml +++ b/app/views/dashboard/_projects.html.haml @@ -1,5 +1,5 @@ -.panel.panel-default - .panel-heading.clearfix +.projects-list-holder + .projects-search-form .input-group = search_field_tag :filter_projects, nil, placeholder: 'Filter by name', class: 'projects-list-filter form-control' - if current_user.can_create_project? @@ -7,4 +7,7 @@ = link_to new_project_path, class: 'btn btn-success' do New project - = render 'shared/projects_list', projects: @projects, projects_limit: 20 + %ul.projects-list.bordered-list.my-projects + - @projects.each do |project| + %li.project-row + = render partial: 'shared/project', locals: { project: project, avatar: true, stars: true } diff --git a/app/views/dashboard/activity.html.haml b/app/views/dashboard/activity.html.haml new file mode 100644 index 00000000000..7a5a093add5 --- /dev/null +++ b/app/views/dashboard/activity.html.haml @@ -0,0 +1,6 @@ += content_for :meta_tags do + - if current_user + = auto_discovery_link_tag(:atom, dashboard_url(format: :atom, private_token: current_user.private_token), title: "All activity") + +%section.activities + = render 'activities' diff --git a/app/views/dashboard/projects/starred.html.haml b/app/views/dashboard/projects/starred.html.haml index 98b8cde4766..6dcfd497ed2 100644 --- a/app/views/dashboard/projects/starred.html.haml +++ b/app/views/dashboard/projects/starred.html.haml @@ -5,10 +5,10 @@ = render 'shared/show_aside' .dashboard.row - %section.activities.col-md-8 + %section.activities.col-md-7 = render 'dashboard/activities' - %aside.col-md-4 - .panel.panel-default + %aside.col-md-5 + .panel.panel-default.projects-list-holder .panel-heading.clearfix .input-group = search_field_tag :filter_projects, nil, placeholder: 'Filter by name', class: 'projects-list-filter form-control' diff --git a/app/views/dashboard/show.html.haml b/app/views/dashboard/show.html.haml index a3a32b6932f..4cf2feb9aa6 100644 --- a/app/views/dashboard/show.html.haml +++ b/app/views/dashboard/show.html.haml @@ -4,14 +4,10 @@ = render 'dashboard/projects_head' -- if @projects.any? - = render 'shared/show_aside' - - .dashboard.row - %section.activities.col-md-8 - = render 'activities' - %aside.col-md-4 - = render 'sidebar' +- if @last_push + = render "events/event_last_push", event: @last_push +- if @projects.any? + = render 'projects' - else = render "zero_authorized_projects" diff --git a/app/views/events/_event_last_push.html.haml b/app/views/events/_event_last_push.html.haml index 501412642db..6a0c6cba41b 100644 --- a/app/views/events/_event_last_push.html.haml +++ b/app/views/events/_event_last_push.html.haml @@ -9,6 +9,6 @@ #{time_ago_with_tooltip(event.created_at)} .pull-right - = link_to new_mr_path_from_push_event(event), title: "New Merge Request", class: "btn btn-create btn-sm" do + = link_to new_mr_path_from_push_event(event), title: "New Merge Request", class: "btn btn-info btn-sm" do Create Merge Request %hr diff --git a/app/views/explore/projects/_project.html.haml b/app/views/explore/projects/_project.html.haml deleted file mode 100644 index 1e8a89e3661..00000000000 --- a/app/views/explore/projects/_project.html.haml +++ /dev/null @@ -1,24 +0,0 @@ -%li - %h4.project-title - .project-access-icon - = visibility_level_icon(project.visibility_level) - = link_to project.name_with_namespace, [project.namespace.becomes(Namespace), project] - %span.pull-right - %i.fa.fa-star - = project.star_count - - .project-info - - if project.description.present? - .project-description.str-truncated - = markdown(project.description, pipeline: :description) - - .repo-info - - unless project.empty_repo? - = link_to pluralize(round_commit_count(project), 'commit'), namespace_project_commits_path(project.namespace, project, project.default_branch) - · - = link_to pluralize(project.repository.branch_names.count, 'branch'), namespace_project_branches_path(project.namespace, project) - · - = link_to pluralize(project.repository.tag_names.count, 'tag'), namespace_project_tags_path(project.namespace, project) - - else - %i.fa.fa-exclamation-triangle - Empty repository diff --git a/app/views/explore/projects/_projects.html.haml b/app/views/explore/projects/_projects.html.haml new file mode 100644 index 00000000000..22cc541115c --- /dev/null +++ b/app/views/explore/projects/_projects.html.haml @@ -0,0 +1,6 @@ +%ul.projects-list.bordered-list.my-projects.public-projects + - projects.each do |project| + %li.project-row + = render partial: 'shared/project', locals: { project: project, avatar: true, stars: true } +- unless projects.present? + .nothing-here-block No such projects diff --git a/app/views/explore/projects/index.html.haml b/app/views/explore/projects/index.html.haml index 4956081e1ed..0cfdf5cfd15 100644 --- a/app/views/explore/projects/index.html.haml +++ b/app/views/explore/projects/index.html.haml @@ -4,10 +4,5 @@ .clearfix = render 'filter' %br -.public-projects - %ul.bordered-list.top-list - = render @projects - - unless @projects.present? - .nothing-here-block No public projects - - = paginate @projects, theme: "gitlab" += render 'projects', projects: @projects += paginate @projects, theme: "gitlab" diff --git a/app/views/explore/projects/starred.html.haml b/app/views/explore/projects/starred.html.haml index fdccbe5692f..4a9fcae4bed 100644 --- a/app/views/explore/projects/starred.html.haml +++ b/app/views/explore/projects/starred.html.haml @@ -7,8 +7,5 @@ See most starred projects .pull-right = render 'explore/projects/dropdown' - .public-projects - %ul.bordered-list - = render @starred_projects - + = render 'projects', projects: @starred_projects = paginate @starred_projects, theme: 'gitlab' diff --git a/app/views/explore/projects/trending.html.haml b/app/views/explore/projects/trending.html.haml index 98a4174b426..4c7e7d44733 100644 --- a/app/views/explore/projects/trending.html.haml +++ b/app/views/explore/projects/trending.html.haml @@ -13,6 +13,4 @@ See most discussed projects for last month .pull-right = render 'explore/projects/dropdown' - .public-projects - %ul.bordered-list - = render @trending_projects + = render 'projects', projects: @trending_projects diff --git a/app/views/groups/_projects.html.haml b/app/views/groups/_projects.html.haml index 4f8aec1c67e..2ae51a1c8c0 100644 --- a/app/views/groups/_projects.html.haml +++ b/app/views/groups/_projects.html.haml @@ -1,4 +1,4 @@ -.panel.panel-default +.panel.panel-default.projects-list-holder .panel-heading.clearfix .input-group = search_field_tag :filter_projects, nil, placeholder: 'Filter by name', class: 'projects-list-filter form-control' diff --git a/app/views/groups/show.html.haml b/app/views/groups/show.html.haml index d31dae7d648..0577f4ec142 100644 --- a/app/views/groups/show.html.haml +++ b/app/views/groups/show.html.haml @@ -17,7 +17,7 @@ = render 'shared/show_aside' .row - %section.activities.col-md-8 + %section.activities.col-md-7 .hidden-xs - if current_user = render "events/event_last_push", event: @last_push @@ -33,5 +33,5 @@ .content_list = spinner - %aside.side.col-md-4 + %aside.side.col-md-5 = render "projects", projects: @projects diff --git a/app/views/layouts/_page.html.haml b/app/views/layouts/_page.html.haml index 96e15783a36..0104d7198df 100644 --- a/app/views/layouts/_page.html.haml +++ b/app/views/layouts/_page.html.haml @@ -1,6 +1,11 @@ .page-with-sidebar{ class: nav_sidebar_class } = render "layouts/broadcast" .sidebar-wrapper.nicescroll + .header-logo + = link_to root_path, class: 'home', title: 'Dashboard', id: 'js-shortcuts-home', data: {toggle: 'tooltip', placement: 'bottom'} do + = brand_header_logo + .gitlab-text-container + %h3 GitLab - if defined?(sidebar) && sidebar = render "layouts/nav/#{sidebar}" - elsif current_user @@ -13,7 +18,7 @@ .username = current_user.username .content-wrapper - .container-fluid + %div{ class: fluid_layout ? "container-fluid" : "container-fluid container-limited" } .content = render "layouts/flash" .clearfix diff --git a/app/views/layouts/header/_default.html.haml b/app/views/layouts/header/_default.html.haml index 12ddbe6f1b7..0b630b55c70 100644 --- a/app/views/layouts/header/_default.html.haml +++ b/app/views/layouts/header/_default.html.haml @@ -1,10 +1,5 @@ %header.navbar.navbar-fixed-top.navbar-gitlab{ class: nav_header_class } - .container - .header-logo - = link_to root_path, class: 'home', title: 'Dashboard', id: 'js-shortcuts-home', data: {toggle: 'tooltip', placement: 'bottom'} do - = brand_header_logo - .gitlab-text-container - %h3 GitLab + %div{ class: fluid_layout ? "container-fluid" : "container-fluid container-limited" } .header-content %button.navbar-toggle{type: 'button'} %span.sr-only Toggle navigation @@ -17,15 +12,6 @@ %li.visible-sm.visible-xs = link_to search_path, title: 'Search', data: {toggle: 'tooltip', placement: 'bottom'} do = icon('search') - -#%li.hidden-xs - = link_to help_path, title: 'Help', data: {toggle: 'tooltip', placement: 'bottom'} do - = icon('question-circle fw') - -#%li - = link_to explore_root_path, title: 'Explore', data: {toggle: 'tooltip', placement: 'bottom'} do - = icon('globe fw') - -#%li - = link_to user_snippets_path(current_user), title: 'Your snippets', data: {toggle: 'tooltip', placement: 'bottom'} do - = icon('clipboard fw') - if current_user.is_admin? %li = link_to admin_root_path, title: 'Admin area', data: {toggle: 'tooltip', placement: 'bottom'} do @@ -34,9 +20,6 @@ %li.hidden-xs = link_to new_project_path, title: 'New project', data: {toggle: 'tooltip', placement: 'bottom'} do = icon('plus fw') - -#%li - = link_to profile_path, title: 'Profile settings', data: {toggle: 'tooltip', placement: 'bottom'} do - = icon('cog fw') %li = link_to destroy_user_session_path, class: 'logout', method: :delete, title: 'Sign out', data: {toggle: 'tooltip', placement: 'bottom'} do = icon('sign-out') diff --git a/app/views/layouts/header/_public.html.haml b/app/views/layouts/header/_public.html.haml index 15c2e292be3..af4b9ba58f6 100644 --- a/app/views/layouts/header/_public.html.haml +++ b/app/views/layouts/header/_public.html.haml @@ -1,10 +1,5 @@ %header.navbar.navbar-fixed-top.navbar-gitlab{ class: nav_header_class } - .container - .header-logo - = link_to explore_root_path, class: "home" do - = brand_header_logo - .gitlab-text-container - %h3 GitLab + %div{ class: fluid_layout ? "container-fluid" : "container-fluid container-limited" } .header-content - unless current_controller?('sessions') .pull-right diff --git a/app/views/layouts/nav/_dashboard.html.haml b/app/views/layouts/nav/_dashboard.html.haml index 8f010196d1a..d620c022273 100644 --- a/app/views/layouts/nav/_dashboard.html.haml +++ b/app/views/layouts/nav/_dashboard.html.haml @@ -1,9 +1,14 @@ %ul.nav.nav-sidebar = nav_link(path: ['dashboard#show', 'root#show', 'projects#trending', 'projects#starred', 'projects#index'], html_options: {class: 'home'}) do = link_to (current_user ? root_path : explore_root_path), title: 'Home', class: 'shortcuts-activity', data: {placement: 'right'} do - = icon('dashboard fw') + = icon('home fw') %span Projects + = nav_link(path: 'dashboard#activity') do + = link_to activity_dashboard_path, title: 'Activity', data: {placement: 'right'} do + = icon('dashboard fw') + %span + Activity = nav_link(controller: :groups) do = link_to (current_user ? dashboard_groups_path : explore_groups_path), title: 'Groups', data: {placement: 'right'} do = icon('group fw') @@ -29,7 +34,7 @@ %span.count= current_user.assigned_merge_requests.opened.count = nav_link(controller: :snippets) do = link_to (current_user ? user_snippets_path(current_user) : snippets_path), title: 'Your snippets', data: {placement: 'right'} do - = icon('dashboard fw') + = icon('clipboard fw') %span Snippets - if current_user diff --git a/app/views/projects/_home_panel.html.haml b/app/views/projects/_home_panel.html.haml index bec40ec27a5..b93036e78e6 100644 --- a/app/views/projects/_home_panel.html.haml +++ b/app/views/projects/_home_panel.html.haml @@ -2,7 +2,7 @@ .project-home-panel.clearfix{:class => ("empty-project" if empty_repo)} .project-identicon-holder = project_icon(@project, alt: '', class: 'project-avatar avatar s90') - .project-home-desc.lead + .project-home-desc %h1= @project.name - if @project.description.present? = markdown(@project.description, pipeline: :description) diff --git a/app/views/projects/blame/show.html.haml b/app/views/projects/blame/show.html.haml index a3ff7ce2f1f..c1ec42aefca 100644 --- a/app/views/projects/blame/show.html.haml +++ b/app/views/projects/blame/show.html.haml @@ -27,7 +27,7 @@ .light = commit_author_link(commit, avatar: false) authored - #{time_ago_with_tooltip(commit.committed_date)} + #{time_ago_with_tooltip(commit.committed_date, skip_js: true)} %td.lines.blame-numbers %pre - line_count = blame_group[:lines].count diff --git a/app/views/projects/buttons/_dropdown.html.haml b/app/views/projects/buttons/_dropdown.html.haml index cade930c8cc..bc7625e8989 100644 --- a/app/views/projects/buttons/_dropdown.html.haml +++ b/app/views/projects/buttons/_dropdown.html.haml @@ -2,7 +2,7 @@ %span.dropdown %a.dropdown-toggle.btn.btn-new{href: '#', "data-toggle" => "dropdown"} = icon('plus') - %ul.dropdown-menu + %ul.dropdown-menu.dropdown-menu-right.project-home-dropdown - if can?(current_user, :create_issue, @project) %li = link_to url_for_new_issue do diff --git a/app/views/projects/deploy_keys/index.html.haml b/app/views/projects/deploy_keys/index.html.haml index 2e9c5dc08c8..8e24c778b7c 100644 --- a/app/views/projects/deploy_keys/index.html.haml +++ b/app/views/projects/deploy_keys/index.html.haml @@ -1,4 +1,5 @@ - page_title "Deploy Keys" + %h3.page-title Deploy keys allow read-only access to the repository diff --git a/app/views/projects/diffs/_diffs.html.haml b/app/views/projects/diffs/_diffs.html.haml index 52c1e03040c..30943f49bba 100644 --- a/app/views/projects/diffs/_diffs.html.haml +++ b/app/views/projects/diffs/_diffs.html.haml @@ -1,3 +1,6 @@ +- if params[:view] == 'parallel' + - fluid_layout true + .prepend-top-20.append-bottom-20 .pull-right .btn-group diff --git a/app/views/projects/diffs/_warning.html.haml b/app/views/projects/diffs/_warning.html.haml index caed0e69dc8..f99bc9a85eb 100644 --- a/app/views/projects/diffs/_warning.html.haml +++ b/app/views/projects/diffs/_warning.html.haml @@ -3,7 +3,7 @@ Too many changes to show. .pull-right - unless diff_hard_limit_enabled? - = link_to "Reload with full diff", url_for(params.merge(force_show_diff: true, format: :html)), class: "btn btn-sm btn-warning" + = link_to "Reload with full diff", url_for(params.merge(force_show_diff: true, format: nil)), class: "btn btn-sm btn-warning" - if current_controller?(:commit) or current_controller?(:merge_requests) - if current_controller?(:commit) diff --git a/app/views/projects/graphs/commits.html.haml b/app/views/projects/graphs/commits.html.haml index 141acbdcf72..a357736bf52 100644 --- a/app/views/projects/graphs/commits.html.haml +++ b/app/views/projects/graphs/commits.html.haml @@ -50,39 +50,42 @@ datasets : [{ fillColor : "rgba(220,220,220,0.5)", strokeColor : "rgba(220,220,220,1)", - pointColor : "rgba(220,220,220,1)", - pointStrokeColor : "#EEE", + barStrokeWidth: 1, + barValueSpacing: 1, + barDatasetSpacing: 1, data : #{@commits_per_time.values.to_json} }] } ctx = $("#hour-chart").get(0).getContext("2d"); - new Chart(ctx).Line(data,{"scaleOverlay": true, responsive: true, pointHitDetectionRadius: 2}) + new Chart(ctx).Bar(data,{"scaleOverlay": true, responsive: true, pointHitDetectionRadius: 2}) data = { labels : #{@commits_per_week_days.keys.to_json}, datasets : [{ fillColor : "rgba(220,220,220,0.5)", strokeColor : "rgba(220,220,220,1)", - pointColor : "rgba(220,220,220,1)", - pointStrokeColor : "#EEE", + barStrokeWidth: 1, + barValueSpacing: 1, + barDatasetSpacing: 1, data : #{@commits_per_week_days.values.to_json} }] } ctx = $("#weekday-chart").get(0).getContext("2d"); - new Chart(ctx).Line(data,{"scaleOverlay": true, responsive: true, pointHitDetectionRadius: 2}) + new Chart(ctx).Bar(data,{"scaleOverlay": true, responsive: true, pointHitDetectionRadius: 2}) data = { labels : #{@commits_per_month.keys.to_json}, datasets : [{ fillColor : "rgba(220,220,220,0.5)", strokeColor : "rgba(220,220,220,1)", - pointColor : "rgba(220,220,220,1)", - pointStrokeColor : "#EEE", + barStrokeWidth: 1, + barValueSpacing: 1, + barDatasetSpacing: 1, data : #{@commits_per_month.values.to_json} }] } ctx = $("#month-chart").get(0).getContext("2d"); - new Chart(ctx).Line(data, {"scaleOverlay": true, responsive: true, pointHitDetectionRadius: 2}) + new Chart(ctx).Bar(data, {"scaleOverlay": true, responsive: true, pointHitDetectionRadius: 2}) diff --git a/app/views/projects/hooks/index.html.haml b/app/views/projects/hooks/index.html.haml index eadbf61fdd4..85dbfd67862 100644 --- a/app/views/projects/hooks/index.html.haml +++ b/app/views/projects/hooks/index.html.haml @@ -55,6 +55,13 @@ %strong Merge Request events %p.light This url will be triggered when a merge request is created + .form-group + = f.label :enable_ssl_verification, "SSL verification", class: 'control-label checkbox' + .col-sm-10 + .checkbox + = f.label :enable_ssl_verification do + = f.check_box :enable_ssl_verification + %strong Enable SSL verification .form-actions = f.submit "Add Web Hook", class: "btn btn-create" @@ -74,3 +81,4 @@ - %w(push_events tag_push_events issues_events note_events merge_requests_events).each do |trigger| - if hook.send(trigger) %span.label.label-gray= trigger.titleize + SSL Verification: #{hook.enable_ssl_verification ? "enabled" : "disabled"} diff --git a/app/views/projects/merge_requests/_show.html.haml b/app/views/projects/merge_requests/_show.html.haml index 007f6c6a787..ec1838eb489 100644 --- a/app/views/projects/merge_requests/_show.html.haml +++ b/app/views/projects/merge_requests/_show.html.haml @@ -1,4 +1,7 @@ - page_title "#{@merge_request.title} (##{@merge_request.iid})", "Merge Requests" +- if params[:view] == 'parallel' + - fluid_layout true + .merge-request{'data-url' => merge_request_path(@merge_request)} .merge-request-details.issuable-details = render "projects/merge_requests/show/mr_title" diff --git a/app/views/shared/_project.html.haml b/app/views/shared/_project.html.haml index 6bd61455d21..15df97b1333 100644 --- a/app/views/shared/_project.html.haml +++ b/app/views/shared/_project.html.haml @@ -3,7 +3,7 @@ - if avatar .dash-project-avatar = project_icon(project, alt: '', class: 'avatar project-avatar s40') - %span.str-truncated + %span.str-truncated.project-full-name %span.namespace-name - if project.namespace = project.namespace.human_name @@ -14,3 +14,7 @@ %span.pull-right.light %i.fa.fa-star = project.star_count + - if project.description.present? + .project-description + .str-truncated + = markdown(project.description, pipeline: :description) diff --git a/app/views/users/show.html.haml b/app/views/users/show.html.haml index 64b7f25ad37..aa4e8722fb1 100644 --- a/app/views/users/show.html.haml +++ b/app/views/users/show.html.haml @@ -7,7 +7,7 @@ = render 'shared/show_aside' .row - %section.col-md-8 + %section.col-md-7 .header-with-avatar = link_to avatar_icon(@user.email, 400), target: '_blank' do = image_tag avatar_icon(@user.email, 90), class: "avatar avatar-tile s90", alt: '' @@ -59,7 +59,7 @@ .content_list = spinner - %aside.col-md-4 + %aside.col-md-5 = render 'profile', user: @user = render 'projects', projects: @projects, contributed_projects: @contributed_projects diff --git a/app/workers/email_receiver_worker.rb b/app/workers/email_receiver_worker.rb index a588a1f45ee..8cfb96ef376 100644 --- a/app/workers/email_receiver_worker.rb +++ b/app/workers/email_receiver_worker.rb @@ -18,6 +18,8 @@ class EmailReceiverWorker def handle_failure(raw, e) Rails.logger.warn("Email can not be processed: #{e}\n\n#{raw}") + return unless raw.present? + can_retry = false reason = nil diff --git a/app/workers/emails_on_push_worker.rb b/app/workers/emails_on_push_worker.rb index 1d21addece6..916a99bb273 100644 --- a/app/workers/emails_on_push_worker.rb +++ b/app/workers/emails_on_push_worker.rb @@ -4,7 +4,7 @@ class EmailsOnPushWorker def perform(project_id, recipients, push_data, options = {}) options.symbolize_keys! options.reverse_merge!( - send_from_committer_email: false, + send_from_committer_email: false, disable_diffs: false ) send_from_committer_email = options[:send_from_committer_email] @@ -16,9 +16,9 @@ class EmailsOnPushWorker ref = push_data["ref"] author_id = push_data["user_id"] - action = + action = if Gitlab::Git.blank_ref?(before_sha) - :create + :create elsif Gitlab::Git.blank_ref?(after_sha) :delete else @@ -42,17 +42,22 @@ class EmailsOnPushWorker end recipients.split(" ").each do |recipient| - Notify.repository_push_email( - project_id, - recipient, - author_id: author_id, - ref: ref, - action: action, - compare: compare, - reverse_compare: reverse_compare, - send_from_committer_email: send_from_committer_email, - disable_diffs: disable_diffs - ).deliver + begin + Notify.repository_push_email( + project_id, + recipient, + author_id: author_id, + ref: ref, + action: action, + compare: compare, + reverse_compare: reverse_compare, + send_from_committer_email: send_from_committer_email, + disable_diffs: disable_diffs + ).deliver + # These are input errors and won't be corrected even if Sidekiq retries + rescue Net::SMTPFatalError, Net::SMTPSyntaxError => e + logger.info("Failed to send e-mail for project '#{project.name_with_namespace}' to #{recipient}: #{e}") + end end ensure compare = nil diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb index bd26ac1da20..c47e5dab27c 100644 --- a/config/initializers/1_settings.rb +++ b/config/initializers/1_settings.rb @@ -8,7 +8,7 @@ class Settings < Settingslogic def gitlab_on_standard_port? gitlab.port.to_i == (gitlab.https ? 443 : 80) end - + # get host without www, thanks to http://stackoverflow.com/a/6674363/1233435 def get_host_without_www(url) url = URI.encode(url) @@ -32,14 +32,12 @@ class Settings < Settingslogic end end + def build_base_gitlab_url + base_gitlab_url.join('') + end + def build_gitlab_url - custom_port = gitlab_on_standard_port? ? nil : ":#{gitlab.port}" - [ gitlab.protocol, - "://", - gitlab.host, - custom_port, - gitlab.relative_url_root - ].join('') + (base_gitlab_url + [gitlab.relative_url_root]).join('') end # check that values in `current` (string or integer) is a contant in `modul`. @@ -64,6 +62,17 @@ class Settings < Settingslogic end value end + + private + + def base_gitlab_url + custom_port = gitlab_on_standard_port? ? nil : ":#{gitlab.port}" + [ gitlab.protocol, + "://", + gitlab.host, + custom_port + ] + end end end @@ -123,6 +132,7 @@ Settings.gitlab['email_enabled'] ||= true if Settings.gitlab['email_enabled'].ni Settings.gitlab['email_from'] ||= "gitlab@#{Settings.gitlab.host}" Settings.gitlab['email_display_name'] ||= "GitLab" Settings.gitlab['email_reply_to'] ||= "noreply@#{Settings.gitlab.host}" +Settings.gitlab['base_url'] ||= Settings.send(:build_base_gitlab_url) Settings.gitlab['url'] ||= Settings.send(:build_gitlab_url) Settings.gitlab['user'] ||= 'git' Settings.gitlab['user_home'] ||= begin diff --git a/config/initializers/omniauth.rb b/config/initializers/omniauth.rb new file mode 100644 index 00000000000..70ed10e8275 --- /dev/null +++ b/config/initializers/omniauth.rb @@ -0,0 +1,28 @@ +if Gitlab::LDAP::Config.enabled? + module OmniAuth::Strategies + server = Gitlab.config.ldap.servers.values.first + klass = server['provider_class'] + const_set(klass, Class.new(LDAP)) unless klass == 'LDAP' + end + + OmniauthCallbacksController.class_eval do + server = Gitlab.config.ldap.servers.values.first + alias_method server['provider_name'], :ldap + end +end + +OmniAuth.config.full_host = Settings.gitlab['base_url'] +OmniAuth.config.allowed_request_methods = [:post] +#In case of auto sign-in, the GET method is used (users don't get to click on a button) +OmniAuth.config.allowed_request_methods << :get if Gitlab.config.omniauth.auto_sign_in_with_provider.present? +OmniAuth.config.before_request_phase do |env| + OmniAuth::RequestForgeryProtection.new(env).call +end + +if Gitlab.config.omniauth.enabled + Gitlab.config.omniauth.providers.each do |provider| + if provider['name'] == 'kerberos' + require 'omniauth-kerberos' + end + end +end diff --git a/config/mail_room.yml.example b/config/mail_room.yml.example index 28366eb7394..dd8edfc42eb 100644 --- a/config/mail_room.yml.example +++ b/config/mail_room.yml.example @@ -14,6 +14,8 @@ # :name: "inbox" # # Always "sidekiq". # :delivery_method: sidekiq + # # Always true. + # :delete_after_delivery: true # :delivery_options: # # The URL to the Redis server used by Sidekiq. Should match the URL in config/resque.yml. # :redis_url: redis://localhost:6379 diff --git a/config/routes.rb b/config/routes.rb index 74544d63d86..3a27571d62b 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -360,6 +360,7 @@ Gitlab::Application.routes.draw do member do get :issues get :merge_requests + get :activity end scope module: :dashboard do diff --git a/db/migrate/20150824002011_add_enable_ssl_verification.rb b/db/migrate/20150824002011_add_enable_ssl_verification.rb new file mode 100644 index 00000000000..093c068fbde --- /dev/null +++ b/db/migrate/20150824002011_add_enable_ssl_verification.rb @@ -0,0 +1,5 @@ +class AddEnableSslVerification < ActiveRecord::Migration + def change + add_column :web_hooks, :enable_ssl_verification, :boolean, default: false + end +end diff --git a/db/schema.rb b/db/schema.rb index 585531c1ee6..77ced9caa3c 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -821,14 +821,14 @@ ActiveRecord::Schema.define(version: 20150826001931) do t.integer "project_id" t.datetime "created_at" t.datetime "updated_at" - t.string "type", default: "ProjectHook" + t.string "type", default: "ProjectHook" t.integer "service_id" - t.boolean "push_events", default: true, null: false - t.boolean "issues_events", default: false, null: false - t.boolean "merge_requests_events", default: false, null: false - t.boolean "tag_push_events", default: false - t.integer "group_id" - t.boolean "note_events", default: false, null: false + t.boolean "push_events", default: true, null: false + t.boolean "issues_events", default: false, null: false + t.boolean "merge_requests_events", default: false, null: false + t.boolean "tag_push_events", default: false + t.boolean "note_events", default: false, null: false + t.boolean "enable_ssl_verification", default: false end add_index "web_hooks", ["created_at", "id"], name: "index_web_hooks_on_created_at_and_id", using: :btree diff --git a/doc/reply_by_email/README.md b/doc/reply_by_email/README.md index 91eea956e52..5d36f5121d1 100644 --- a/doc/reply_by_email/README.md +++ b/doc/reply_by_email/README.md @@ -59,6 +59,8 @@ In this example, we'll use the Gmail address `gitlab-replies@gmail.com`. If you' :name: "inbox" # Always "sidekiq". :delivery_method: sidekiq + # Always true. + :delete_after_delivery: true :delivery_options: # The URL to the Redis server used by Sidekiq. Should match the URL in config/resque.yml. :redis_url: redis://localhost:6379 @@ -144,6 +146,8 @@ TODO :name: "inbox" # Always "sidekiq". :delivery_method: sidekiq + # Always true. + :delete_after_delivery: true :delivery_options: # The URL to the Redis server used by Sidekiq. Should match the URL in config/resque.yml. :redis_url: redis://localhost:6379 diff --git a/doc/workflow/importing/README.md b/doc/workflow/importing/README.md index cd98d1b9852..5cde90993d2 100644 --- a/doc/workflow/importing/README.md +++ b/doc/workflow/importing/README.md @@ -8,5 +8,5 @@ ### Note
* If you'd like to migrate from a self-hosted GitLab instance to GitLab.com, you can copy your repos by changing the remote and pushing to the new server; but issues and merge requests can't be imported.
-* Repositories are imported to GitLab via HTTP.
-If the repository is too large, it can timeout. We have a soft limit of 10GB.
+* You can import any Git repository via HTTP from the New Project page.
+If the repository is too large, it can timeout.
diff --git a/features/admin/hooks.feature b/features/admin/hooks.feature new file mode 100644 index 00000000000..5ca332d9f1c --- /dev/null +++ b/features/admin/hooks.feature @@ -0,0 +1,9 @@ +@admin +Feature: Admin Hooks + Background: + Given I sign in as an admin + + Scenario: On Admin Hooks + Given I visit admin hooks page + Then I submit the form with enabled SSL verification + And I see new hook with enabled SSL verification
\ No newline at end of file diff --git a/features/dashboard/dashboard.feature b/features/dashboard/dashboard.feature index 1959d327082..392d4235eff 100644 --- a/features/dashboard/dashboard.feature +++ b/features/dashboard/dashboard.feature @@ -10,6 +10,10 @@ Feature: Dashboard Scenario: I should see projects list Then I should see "New Project" link Then I should see "Shop" project link + + @javascript + Scenario: I should see activity list + And I visit dashboard activity page Then I should see project "Shop" activity feed Scenario: I should see groups list @@ -26,12 +30,12 @@ Feature: Dashboard @javascript Scenario: I should see User joined Project event Given user with name "John Doe" joined project "Shop" - When I visit dashboard page + When I visit dashboard activity page Then I should see "John Doe joined project Shop" event @javascript Scenario: I should see User left Project event Given user with name "John Doe" joined project "Shop" And user with name "John Doe" left project "Shop" - When I visit dashboard page + When I visit dashboard activity page Then I should see "John Doe left project Shop" event diff --git a/features/dashboard/event_filters.feature b/features/dashboard/event_filters.feature index ec5680caba6..96399ea21a6 100644 --- a/features/dashboard/event_filters.feature +++ b/features/dashboard/event_filters.feature @@ -6,7 +6,7 @@ Feature: Event Filters And this project has push event And this project has new member event And this project has merge request event - And I visit dashboard page + And I visit dashboard activity page @javascript Scenario: I should see all events @@ -16,7 +16,7 @@ Feature: Event Filters @javascript Scenario: I should see only pushed events - When I click "push" event filter + When I click "push" event filter Then I should see push event And I should not see new member event And I should not see merge request event @@ -38,11 +38,11 @@ Feature: Event Filters @javascript Scenario: I should see only selected events while page reloaded When I click "push" event filter - And I visit dashboard page + And I visit dashboard activity page Then I should see push event And I should not see new member event When I click "team" event filter - And I visit dashboard page + And I visit dashboard activity page Then I should see push event And I should see new member event And I should not see merge request event diff --git a/features/project/commits/commits.feature b/features/project/commits/commits.feature index c4b206edc95..3ebc8a39aae 100644 --- a/features/project/commits/commits.feature +++ b/features/project/commits/commits.feature @@ -41,6 +41,7 @@ Feature: Project Commits Scenario: I browse big commit Given I visit big commit page Then I see big commit warning + And I see "Reload with full diff" link Scenario: I browse a commit with an image Given I visit a commit with an image that changed diff --git a/features/project/hooks.feature b/features/project/hooks.feature index 1a60846a23e..627738004c4 100644 --- a/features/project/hooks.feature +++ b/features/project/hooks.feature @@ -13,6 +13,11 @@ Feature: Project Hooks When I submit new hook Then I should see newly created hook + Scenario: I add new hook with SSL verification enabled + Given I visit project hooks page + When I submit new hook with SSL verification enabled + Then I should see newly created hook with SSL verification enabled + Scenario: I test hook Given project has hook And I visit project hooks page diff --git a/features/steps/admin/hooks.rb b/features/steps/admin/hooks.rb new file mode 100644 index 00000000000..541e25fcb70 --- /dev/null +++ b/features/steps/admin/hooks.rb @@ -0,0 +1,15 @@ +class Spinach::Features::AdminHooks < Spinach::FeatureSteps + include SharedAuthentication + include SharedPaths + include SharedAdmin + + step "I submit the form with enabled SSL verification" do + fill_in 'hook_url', with: 'http://google.com' + check "Enable SSL verification" + click_on "Add System Hook" + end + + step "I see new hook with enabled SSL verification" do + expect(page).to have_content "SSL Verification: enabled" + end +end diff --git a/features/steps/project/commits/commits.rb b/features/steps/project/commits/commits.rb index e6330ec457e..a8532cc18d8 100644 --- a/features/steps/project/commits/commits.rb +++ b/features/steps/project/commits/commits.rb @@ -79,6 +79,12 @@ class Spinach::Features::ProjectCommits < Spinach::FeatureSteps expect(page).to have_content "Too many changes" end + step 'I see "Reload with full diff" link' do + link = find_link('Reload with full diff') + expect(link[:href]).to end_with('?force_show_diff=true') + expect(link[:href]).not_to include('.html') + end + step 'I visit a commit with an image that changed' do visit namespace_project_commit_path(@project.namespace, @project, sample_image_commit.id) end diff --git a/features/steps/project/hooks.rb b/features/steps/project/hooks.rb index 04e3bf78ede..df4a23a3716 100644 --- a/features/steps/project/hooks.rb +++ b/features/steps/project/hooks.rb @@ -28,11 +28,24 @@ class Spinach::Features::ProjectHooks < Spinach::FeatureSteps expect { click_button "Add Web Hook" }.to change(ProjectHook, :count).by(1) end + step 'I submit new hook with SSL verification enabled' do + @url = FFaker::Internet.uri("http") + fill_in "hook_url", with: @url + check "hook_enable_ssl_verification" + expect { click_button "Add Web Hook" }.to change(ProjectHook, :count).by(1) + end + step 'I should see newly created hook' do expect(current_path).to eq namespace_project_hooks_path(current_project.namespace, current_project) expect(page).to have_content(@url) end + step 'I should see newly created hook with SSL verification enabled' do + expect(current_path).to eq namespace_project_hooks_path(current_project.namespace, current_project) + expect(page).to have_content(@url) + expect(page).to have_content("SSL Verification: enabled") + end + step 'I click test hook button' do stub_request(:post, @hook.url).to_return(status: 200) click_link 'Test Hook' diff --git a/features/steps/shared/paths.rb b/features/steps/shared/paths.rb index ca8fbb49101..b4deccb6520 100644 --- a/features/steps/shared/paths.rb +++ b/features/steps/shared/paths.rb @@ -71,6 +71,10 @@ module SharedPaths visit dashboard_path end + step 'I visit dashboard activity page' do + visit activity_dashboard_path + end + step 'I visit dashboard projects page' do visit projects_dashboard_path end diff --git a/lib/support/init.d/gitlab b/lib/support/init.d/gitlab index 41a2f254db6..457bd31e23b 100755 --- a/lib/support/init.d/gitlab +++ b/lib/support/init.d/gitlab @@ -288,7 +288,7 @@ print_status() { fi if [ "$mail_room_enabled" = true ]; then if [ "$mail_room_status" = "0" ]; then - echo "The GitLab MailRoom email processor with pid $spid is running." + echo "The GitLab MailRoom email processor with pid $mpid is running." else printf "The GitLab MailRoom email processor is \033[31mnot running\033[0m.\n" fi diff --git a/spec/lib/gitlab/markdown/user_reference_filter_spec.rb b/spec/lib/gitlab/markdown/user_reference_filter_spec.rb index a5405e14a73..02d923b036c 100644 --- a/spec/lib/gitlab/markdown/user_reference_filter_spec.rb +++ b/spec/lib/gitlab/markdown/user_reference_filter_spec.rb @@ -121,7 +121,6 @@ module Gitlab::Markdown end it 'links with adjacent text' do - skip "TODO (rspeicher): Re-enable when usernames can't end in periods." doc = filter("Mention me (#{reference}.)") expect(doc.to_html).to match(/\(<a.+>#{reference}<\/a>\.\)/) end diff --git a/spec/workers/emails_on_push_worker_spec.rb b/spec/workers/emails_on_push_worker_spec.rb new file mode 100644 index 00000000000..3600c771075 --- /dev/null +++ b/spec/workers/emails_on_push_worker_spec.rb @@ -0,0 +1,34 @@ +require 'spec_helper' + +describe EmailsOnPushWorker do + include RepoHelpers + + let(:project) { create(:project) } + let(:user) { create(:user) } + let(:data) { Gitlab::PushDataBuilder.build_sample(project, user) } + + subject { EmailsOnPushWorker.new } + + before do + allow(Project).to receive(:find).and_return(project) + end + + describe "#perform" do + it "sends mail" do + subject.perform(project.id, user.email, data.stringify_keys) + + email = ActionMailer::Base.deliveries.last + expect(email.subject).to include('Change some files') + expect(email.to).to eq([user.email]) + end + + it "gracefully handles an input SMTP error" do + ActionMailer::Base.deliveries.clear + allow(Notify).to receive(:repository_push_email).and_raise(Net::SMTPFatalError) + + subject.perform(project.id, user.email, data.stringify_keys) + + expect(ActionMailer::Base.deliveries.count).to eq(0) + end + end +end |