diff --git a/CHANGELOG b/CHANGELOG index 03b12ff1331e1bfa284aecc687dba54fe00168c1..386ce7ca6d4ff8247d80a40482bb163254f98fd3 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,9 +1,9 @@ Please view this file on the master branch, on stable branches it's out of date. v 8.0.0 (unreleased) + - 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) - - Fix "Reload with full diff" URL button in compare branch view (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 @@ -16,14 +16,19 @@ v 8.0.0 (unreleased) - 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) - - Improve abuse reports management from admin area - 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 + - Fix 500 error when submit project snippet without body + - Improve search page usability + - Bring more UI consistency in way how projects, snippets and groups lists are rendered -v 7.14.1 (unreleased) +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. diff --git a/Gemfile b/Gemfile index fa54a72f025339614fdb70f7c8144fd4b630259b..4696a961e824955f90aaef62fe8806068251b65a 100644 --- a/Gemfile +++ b/Gemfile @@ -273,6 +273,6 @@ gem "newrelic_rpm" gem 'octokit', '3.7.0' -gem "mail_room", "~> 0.4.0" +gem "mail_room", "~> 0.4.1" gem 'email_reply_parser' diff --git a/Gemfile.lock b/Gemfile.lock index a7cfe6b75111d131ba786efe5e77bfdca9636224..814249c7ff660937f41e9be29ca7a911a25fd43d 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -372,7 +372,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) @@ -808,7 +808,7 @@ DEPENDENCIES jquery-ui-rails kaminari (~> 0.15.1) letter_opener - mail_room (~> 0.4.0) + mail_room (~> 0.4.1) minitest (~> 5.3.0) mousetrap-rails mysql2 diff --git a/app/assets/javascripts/dispatcher.js.coffee b/app/assets/javascripts/dispatcher.js.coffee index 539041c28621a8edb73174b897ae8d53633e0be1..5bf0b302179f4cda666bf23647a33b90c1450e86 100644 --- a/app/assets/javascripts/dispatcher.js.coffee +++ b/app/assets/javascripts/dispatcher.js.coffee @@ -55,7 +55,6 @@ class Dispatcher new Activities() when 'dashboard:projects:starred' new Activities() - new ProjectsList() when 'projects:commit:show' new Commit() new Diff() @@ -70,7 +69,6 @@ class Dispatcher when 'groups:show' new Activities() shortcut_handler = new ShortcutsNavigation() - new ProjectsList() when 'groups:group_members:index' new GroupMembers() new UsersSelect() @@ -96,8 +94,6 @@ class Dispatcher when 'users:show' new User() new Activities() - when 'admin:users:show' - new ProjectsList() switch path.first() when 'admin' diff --git a/app/assets/stylesheets/base/mixins.scss b/app/assets/stylesheets/base/mixins.scss index 7beef1845ef7ec41a70a1d42abf04a713bf55911..05f5bd79f91e96613f69188d9df8bf7a7961775b 100644 --- a/app/assets/stylesheets/base/mixins.scss +++ b/app/assets/stylesheets/base/mixins.scss @@ -157,3 +157,41 @@ white-space: nowrap; max-width: $max_width; } + +/* + * Base mixin for lists in GitLab + */ +@mixin basic-list { + margin: 5px 0px; + padding: 0px; + list-style: none; + + li { + padding: 10px 0; + border-bottom: 1px solid #EEE; + overflow: hidden; + display: block; + margin: 0px; + + &:last-child { + border:none + } + + &.active { + background: #f9f9f9; + a { + font-weight: bold; + } + } + + &.hide { + display: none; + } + + &.light { + a { + color: #777; + } + } + } +} diff --git a/app/assets/stylesheets/generic/common.scss b/app/assets/stylesheets/generic/common.scss index bf5c7a8d75ebbeb7cd099dc5794e33906fb0a85f..2674fde41ae7fc650639f0ffdab204856fa3931b 100644 --- a/app/assets/stylesheets/generic/common.scss +++ b/app/assets/stylesheets/generic/common.scss @@ -375,9 +375,9 @@ table { } .center-top-menu { - border-bottom: 1px solid #EEE; list-style: none; text-align: center; + margin-top: 5px; padding-bottom: 15px; margin-bottom: 15px; @@ -385,7 +385,7 @@ table { display: inline-block; a { - padding: 10px; + padding: 15px; } &.active a { diff --git a/app/assets/stylesheets/generic/lists.scss b/app/assets/stylesheets/generic/lists.scss index c502d953c7573c0fc9b20c78f9e98fbd9e5f270a..4b7ff84de2b31f9462272f59250324aa69a5b9c2 100644 --- a/app/assets/stylesheets/generic/lists.scss +++ b/app/assets/stylesheets/generic/lists.scss @@ -93,28 +93,12 @@ ol, ul { /** light list with border-bottom between li **/ ul.bordered-list { - margin: 5px 0px; - padding: 0px; - li { - padding: 5px 0; - border-bottom: 1px solid #EEE; - overflow: hidden; - display: block; - margin: 0px; - &:last-child { border:none } - &.active { - background: #f9f9f9; - a { font-weight: bold; } - } - - &.light { - a { color: #777; } - } - } + @include basic-list; &.top-list { li:first-child { padding-top: 0; + h4, h5 { margin-top: 0; } diff --git a/app/assets/stylesheets/pages/projects.scss b/app/assets/stylesheets/pages/projects.scss index 4d065c3bdf693e992c3e3eeefa2edb12d58bc589..488dded549edb8729c735eaf38fae2c9f0b541f2 100644 --- a/app/assets/stylesheets/pages/projects.scss +++ b/app/assets/stylesheets/pages/projects.scss @@ -162,78 +162,6 @@ ul.nav.nav-projects-tabs { margin: 0px; } -.my-projects, -.public-projects { - li { - .project-info { - margin-bottom: 10px; - overflow: hidden; - } - - .access-icon { - color: #AAA; - margin-left: 10px; - i { - color: #AAA; - } - } - } -} - -.public-clone { - background: #EEE; - color: #777; - padding: 6px 10px; - margin: 1px; - font-weight: normal; -} - -.public-projects .repo-info { - color: #777; - - a { - color: #777; - } -} - -.project-side { - .project-fork-icon { - float: left; - font-size: 26px; - margin-right: 10px; - line-height: 1.5; - } - - .panel { - @include border-radius(3px); - - .panel-heading, .panel-footer { - font-weight: normal; - background-color: transparent; - color: #666; - border-color: #EEE; - } - - .actions { - margin-top: 10px; - } - - .nav-pills a { - padding: 10px; - font-weight: bold; - color: $gl-link-color; - } - - .nav { - margin-bottom: 15px; - } - } - - .ci-status-image { - max-height: 22px; - } -} - .transfer-project .select2-container { min-width: 200px; } @@ -334,23 +262,32 @@ pre.light-well { } } -.project-row { - .project-full-name { - font-weight: bold; - font-size: 15px; - } +/* + * Projects list rendered on dashboard and user page + */ +.projects-list { + @include basic-list; - .project-description { - color: #888; - font-size: 13px; + .project-row { + .project-full-name { + @include str-truncated; + font-weight: bold; + font-size: 15px; + } - p { - margin-bottom: 0; + .project-description { color: #888; + font-size: 13px; + + p { + @include str-truncated; + margin-bottom: 0; + color: #888; + } } } } -.my-projects .project-row { - padding: 10px 0; +.panel .projects-list li { + padding: 10px 15px; } diff --git a/app/assets/stylesheets/pages/search.scss b/app/assets/stylesheets/pages/search.scss index bdaa17ac33926839777bcfdf84fe8d2c565bff1e..3aaa96da609172170cb7dc5907cf751e77d57cf1 100644 --- a/app/assets/stylesheets/pages/search.scss +++ b/app/assets/stylesheets/pages/search.scss @@ -1,7 +1,19 @@ .search-results { .search-result-row { - border-bottom: 1px solid #EEE; - padding-bottom: 10px; - margin-bottom: 10px; + border-bottom: 1px solid #DDD; + padding-bottom: 15px; + margin-bottom: 15px; } } + +.search-holder { + max-width: 600px; + margin: 0 auto; + margin-bottom: 20px; + + input { + border-color: #BBB; + font-weight: bold; + } +} + diff --git a/app/assets/stylesheets/pages/snippets.scss b/app/assets/stylesheets/pages/snippets.scss index d79591d99156ffbfef51dec3772452777c6d53f8..a3d7aba054d21d654efe5152023b67910bb772d6 100644 --- a/app/assets/stylesheets/pages/snippets.scss +++ b/app/assets/stylesheets/pages/snippets.scss @@ -6,3 +6,27 @@ .snippet-form-holder .file-holder .file-title { padding: 2px; } + + +.snippet-row { + .snippet-title { + font-size: 15px; + font-weight: bold; + line-height: 20px; + margin-bottom: 2px; + + .monospace { + font-weight: normal; + } + } + + .snippet-info { + color: #888; + font-size: 13px; + line-height: 24px; + + a { + color: #888; + } + } +} diff --git a/app/controllers/admin/hooks_controller.rb b/app/controllers/admin/hooks_controller.rb index 690096bdbcf5ff05ae66d0ad4e61afcf61556313..d670386f8c62afdca3ef174da86df8dae1de4cba 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 12d439b0b312b4775d13319a8aebcd4106b3241f..ef1170e16da6c83254b808804761aa197673b3e6 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -55,7 +55,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/projects/hooks_controller.rb b/app/controllers/projects/hooks_controller.rb index 76062446c92765be86eb2c2dc6846651505f097d..4e5b4125f5a9cbaa654066ad9e1ae745c7cfeb2e 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 0110553247959d85b490f4efb5705cbbe1c4514f..b0cf5866d41033b9367d10675cc9b91f83eaa350 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/controllers/projects/snippets_controller.rb b/app/controllers/projects/snippets_controller.rb index 643066374230cc5038b21410659073d0af473517..b07a2a8db2f7d121a5f8ad50a1c8d1433725d5f3 100644 --- a/app/controllers/projects/snippets_controller.rb +++ b/app/controllers/projects/snippets_controller.rb @@ -30,9 +30,14 @@ class Projects::SnippetsController < Projects::ApplicationController def create @snippet = CreateSnippetService.new(@project, current_user, snippet_params).execute - respond_with(@snippet, - location: namespace_project_snippet_path(@project.namespace, - @project, @snippet)) + + if @snippet.valid? + respond_with(@snippet, + location: namespace_project_snippet_path(@project.namespace, + @project, @snippet)) + else + render :new + end end def edit diff --git a/app/finders/trending_projects_finder.rb b/app/finders/trending_projects_finder.rb index a79bd47d9867de5379cd985b16cf3a0683e1fb74..f3f4d461efa3680a19b6cc04bb894d339a3a92ad 100644 --- a/app/finders/trending_projects_finder.rb +++ b/app/finders/trending_projects_finder.rb @@ -2,13 +2,21 @@ class TrendingProjectsFinder def execute(current_user, start_date = nil) start_date ||= Date.today - 1.month - projects = projects_for(current_user) - # Determine trending projects based on comments count # for period of time - ex. month - projects.joins(:notes).where('notes.created_at > ?', start_date). - select("projects.*, count(notes.id) as ncount"). - group("projects.id").reorder("ncount DESC") + trending_project_ids = Note. + select("notes.project_id, count(notes.project_id) as pcount"). + where('notes.created_at > ?', start_date). + group("project_id"). + reorder("pcount DESC"). + map(&:project_id) + + sql_order_ids = trending_project_ids.reverse. + map { |project_id| "id = #{project_id}" }.join(", ") + + # Get list of projects that user allowed to see + projects = projects_for(current_user) + projects.where(id: trending_project_ids).reorder(sql_order_ids) end private diff --git a/app/models/hooks/web_hook.rb b/app/models/hooks/web_hook.rb index 46fb85336e537f0c092217e246bf24b9798c7ac0..9a8251bdad510d28be28f2bc5c5e091a60a41e8c 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 a714bc82246d778742b7497d657750b8b79272eb..9e5da6f45d2444e44e7b3356363617ff22ff5ec3 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 ecdcd48ae602476d8670fae8352fc7ed14cd718c..acbbc9935b62705d6d0be647388bdff9b2ed69c4 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/hooks/index.html.haml b/app/views/admin/hooks/index.html.haml index e74e1e85f4165251dc1f8f7d1cf988c01584397c..b120f4dea67b675ea92c6d84a3405ac60eaa6b5f 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 dc83d5343f2c671c35fc6ebaaccb2cb34366a1b9..ef9b9ce756acb29a1a7a644633bdd9b8d9d52e83 100644 --- a/app/views/dashboard/_projects.html.haml +++ b/app/views/dashboard/_projects.html.haml @@ -7,7 +7,4 @@ = link_to new_project_path, class: 'btn btn-success' do New project - %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 } + = render 'shared/projects/list', projects: @projects diff --git a/app/views/dashboard/groups/index.html.haml b/app/views/dashboard/groups/index.html.haml index 0860fe3c761e577c53f5fa4c2b8870d680f14793..fbe523b4b66423dd3ba9ebd8e1a796d40446782a 100644 --- a/app/views/dashboard/groups/index.html.haml +++ b/app/views/dashboard/groups/index.html.haml @@ -8,32 +8,9 @@ = link_to new_group_path, class: "btn btn-new btn-sm" do %i.fa.fa-plus New Group -.panel.panel-default - .panel-heading - %strong Groups - (#{@group_members.count}) - %ul.well-list - - @group_members.each do |group_member| - - group = group_member.group - %li - .pull-right.hidden-xs - - if can?(current_user, :admin_group, group) - = link_to edit_group_path(group), class: "btn-sm btn btn-grouped" do - %i.fa.fa-cogs - Settings - - = link_to leave_group_group_members_path(group), data: { confirm: leave_group_message(group.name) }, method: :delete, class: "btn-sm btn btn-grouped", title: 'Leave this group' do - %i.fa.fa-sign-out - Leave - - = image_tag group_icon(group), class: "avatar s40 avatar-tile hidden-xs" - = link_to group, class: 'group-name' do - %strong= group.name - - as - %strong #{group_member.human_access} - - %div.light - #{pluralize(group.projects.count, "project")}, #{pluralize(group.users.count, "user")} +%ul.bordered-list + - @group_members.each do |group_member| + - group = group_member.group + = render 'shared/groups/group', group: group, group_member: group_member = paginate @group_members diff --git a/app/views/dashboard/projects/starred.html.haml b/app/views/dashboard/projects/starred.html.haml index 6dcfd497ed2acdd0976da3d31911f3b7eae37f06..19f3975e530f1924d95060d2d6bb7a571757117f 100644 --- a/app/views/dashboard/projects/starred.html.haml +++ b/app/views/dashboard/projects/starred.html.haml @@ -17,8 +17,7 @@ = link_to new_project_path, class: 'btn btn-success' do New project - = render 'shared/projects_list', projects: @projects, - projects_limit: 20, stars: true, avatar: false + = render 'shared/projects/list', projects: @projects, projects_limit: 20 - else %h3 You don't have starred projects yet diff --git a/app/views/explore/groups/index.html.haml b/app/views/explore/groups/index.html.haml index 7dcefd330a14930befe7c74ad0c4993712b5f6e9..80acb91436599f5e3205744bf35beb8013f9d301 100644 --- a/app/views/explore/groups/index.html.haml +++ b/app/views/explore/groups/index.html.haml @@ -32,17 +32,7 @@ %ul.bordered-list - @groups.each do |group| - %li - .clearfix - %h4 - = link_to group_path(id: group.path) do - = group.name - .clearfix - %p - = truncate group.description, length: 150 - .clearfix - %p.light - #{pluralize(group.members.size, 'member')}, #{pluralize(group.projects.count, 'project')} + = render 'shared/groups/group', group: group - unless @groups.present? .nothing-here-block No public groups diff --git a/app/views/explore/projects/_projects.html.haml b/app/views/explore/projects/_projects.html.haml index 22cc541115c010dd165c61728712a20e1d7f2d36..669079e9521733e02500e87d32c8b81b6c87f766 100644 --- a/app/views/explore/projects/_projects.html.haml +++ b/app/views/explore/projects/_projects.html.haml @@ -1,6 +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 +- if projects.any? + .public-projects + = render 'shared/projects/list', projects: projects +- else + .nothing-here-block + No such projects diff --git a/app/views/groups/_projects.html.haml b/app/views/groups/_projects.html.haml index 2ae51a1c8c0c51820be1bf6a5afe298cd843f4c8..b2e32ced5e0f614581019282bda595c050de6469 100644 --- a/app/views/groups/_projects.html.haml +++ b/app/views/groups/_projects.html.haml @@ -7,4 +7,4 @@ = link_to new_project_path(namespace_id: @group.id), class: 'btn btn-success' do New project - = render 'shared/projects_list', projects: @projects, projects_limit: 20 + = render 'shared/projects/list', projects: @projects, projects_limit: 20 diff --git a/app/views/layouts/nav/_project.html.haml b/app/views/layouts/nav/_project.html.haml index d17d1c5fbd48cb5b5f3ede5fe8b2ff3168f04a9b..5e7b902622bf65bceceeb8b93d07841acd2d6c7c 100644 --- a/app/views/layouts/nav/_project.html.haml +++ b/app/views/layouts/nav/_project.html.haml @@ -100,7 +100,7 @@ - if project_nav_tab? :snippets = nav_link(controller: :snippets) do = link_to namespace_project_snippets_path(@project.namespace, @project), title: 'Snippets', class: 'shortcuts-snippets', data: {placement: 'right'} do - = icon('file-text-o fw') + = icon('clipboard fw') %span Snippets diff --git a/app/views/projects/hooks/index.html.haml b/app/views/projects/hooks/index.html.haml index eadbf61fdd4ed32f75995b2997a2601f4bc1c39f..85dbfd6786258ffc7dbf9b4daa554cccc5a1abbc 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/snippets/_snippet.html.haml b/app/views/projects/snippets/_snippet.html.haml deleted file mode 100644 index b2c35edc44c653e011712dbbb54e26040affeb9a..0000000000000000000000000000000000000000 --- a/app/views/projects/snippets/_snippet.html.haml +++ /dev/null @@ -1,15 +0,0 @@ -%li - %h4.snippet-title - = link_to reliable_snippet_path(snippet) do - = truncate(snippet.title, length: 60) - %span.cgray.monospace.tiny.pull-right - = snippet.file_name - - .snippet-info - = "##{snippet.id}" - %span - by - = image_tag avatar_icon(snippet.author_email), class: "avatar avatar-inline s16" - = snippet.author_name - %span.light - #{time_ago_with_tooltip(snippet.created_at)} diff --git a/app/views/projects/snippets/index.html.haml b/app/views/projects/snippets/index.html.haml index 30081673ffc76b4c2850a98b8358cf327b4bfa4c..45d4de6a385b4cc0b17d50a208218df97d901f23 100644 --- a/app/views/projects/snippets/index.html.haml +++ b/app/views/projects/snippets/index.html.haml @@ -8,9 +8,8 @@ %p.light Share code pastes with others out of git repository -%hr %ul.bordered-list - = render partial: "projects/snippets/snippet", collection: @snippets + = render partial: "shared/snippets/snippet", collection: @snippets - if @snippets.empty? %li .nothing-here-block Nothing here. diff --git a/app/views/search/_category.html.haml b/app/views/search/_category.html.haml index a75cd7bd8096e7286af0aef5b77891342b564104..d637abfa76b90588840b1e98c209e0c7521b7fd4 100644 --- a/app/views/search/_category.html.haml +++ b/app/views/search/_category.html.haml @@ -1,4 +1,4 @@ -%ul.nav.nav-pills.search-filter +%ul.nav.nav-tabs.search-filter - if @project %li{class: ("active" if @scope == 'blobs')} = link_to search_filter_path(scope: 'blobs') do diff --git a/app/views/search/_filter.html.haml b/app/views/search/_filter.html.haml index e2d0cab9e79bfe18132054e8aa9ae538ba00c53a..ec478a5963d15d75fb75cc6f7caf9b80b891611c 100644 --- a/app/views/search/_filter.html.haml +++ b/app/views/search/_filter.html.haml @@ -1,6 +1,5 @@ .dropdown.inline - %button.dropdown-toggle.btn.btn{type: 'button', 'data-toggle' => 'dropdown'} - %i.fa.fa-tags + %button.dropdown-toggle.btn.btn-sm{type: 'button', 'data-toggle' => 'dropdown'} %span.light Group: - if @group.present? %strong= @group.name @@ -17,8 +16,7 @@ = group.name .dropdown.inline.prepend-left-10.project-filter - %button.dropdown-toggle.btn.btn{type: 'button', 'data-toggle' => 'dropdown'} - %i.fa.fa-tags + %button.dropdown-toggle.btn.btn-sm{type: 'button', 'data-toggle' => 'dropdown'} %span.light Project: - if @project.present? %strong= @project.name_with_namespace diff --git a/app/views/search/_form.html.haml b/app/views/search/_form.html.haml index 5ee70be1ad6b44ee8fa894db5ed2b80f8e4592e2..3938c545caddd0bbbc7948b22026c83fbc3fc835 100644 --- a/app/views/search/_form.html.haml +++ b/app/views/search/_form.html.haml @@ -1,12 +1,14 @@ -= form_tag search_path, method: :get, class: 'form-inline' do |f| += form_tag search_path, method: :get do |f| = hidden_field_tag :project_id, params[:project_id] = hidden_field_tag :group_id, params[:group_id] = hidden_field_tag :snippets, params[:snippets] = hidden_field_tag :scope, params[:scope] + .search-holder.clearfix - .form-group + .input-group = search_field_tag :search, params[:search], placeholder: "Search for projects, issues etc", class: "form-control search-text-input", id: "dashboard_search", autofocus: true - = button_tag 'Search', class: "btn btn-primary" + %span.input-group-btn + = button_tag 'Search', class: "btn btn-primary" - unless params[:snippets].eql? 'true' - .pull-right - = render 'filter' + %br + = render 'filter' diff --git a/app/views/search/_results.html.haml b/app/views/search/_results.html.haml index 741c780ad96921da5c45bd48ed063c7c673c2a2a..2a38c98dcfcc17dc205f6c49d26b4f69c8a05452 100644 --- a/app/views/search/_results.html.haml +++ b/app/views/search/_results.html.haml @@ -1,7 +1,7 @@ - if @search_results.empty? = render partial: "search/results/empty" - else - .light + %p.light Search results for %code = @search_term @@ -11,10 +11,13 @@ - elsif @group in group #{link_to @group.name, @group} - %br .results.prepend-top-10 .search-results - = render partial: "search/results/#{@scope.singularize}", collection: @objects + - if @scope == 'projects' + .term + = render 'shared/projects/list', projects: @objects + - else + = render partial: "search/results/#{@scope.singularize}", collection: @objects = paginate @objects, theme: 'gitlab' :javascript diff --git a/app/views/search/results/_project.html.haml b/app/views/search/results/_project.html.haml deleted file mode 100644 index 195cf06c8ea73fa1b208d7f7556ddef491985ae8..0000000000000000000000000000000000000000 --- a/app/views/search/results/_project.html.haml +++ /dev/null @@ -1,6 +0,0 @@ -.search-result-row - %h4 - = link_to [project.namespace.becomes(Namespace), project] do - %span.term= project.name_with_namespace - - if project.description.present? - %span.light.term= project.description diff --git a/app/views/search/show.html.haml b/app/views/search/show.html.haml index 60f9e9ac9de07b3a20ab866f96f83d9066fe097c..f4f3dcfc29ff5ba1ebe68709264f50e7adaa4ac9 100644 --- a/app/views/search/show.html.haml +++ b/app/views/search/show.html.haml @@ -1,7 +1,5 @@ - page_title @search_term = render 'search/form' -%hr - if @search_term = render 'search/category' - %hr = render 'search/results' diff --git a/app/views/shared/_project.html.haml b/app/views/shared/_project.html.haml deleted file mode 100644 index 15df97b133315645ec8e1603f302221996450795..0000000000000000000000000000000000000000 --- a/app/views/shared/_project.html.haml +++ /dev/null @@ -1,20 +0,0 @@ -= cache [project.namespace, project, controller.controller_name, controller.action_name] do - = link_to project_path(project), class: dom_class(project) do - - if avatar - .dash-project-avatar - = project_icon(project, alt: '', class: 'avatar project-avatar s40') - %span.str-truncated.project-full-name - %span.namespace-name - - if project.namespace - = project.namespace.human_name - \/ - %span.project-name.filter-title - = project.name - - if stars - %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/shared/_projects_list.html.haml b/app/views/shared/_projects_list.html.haml deleted file mode 100644 index 4c58092af44ca17c60a75dd231dc87e5556bd179..0000000000000000000000000000000000000000 --- a/app/views/shared/_projects_list.html.haml +++ /dev/null @@ -1,17 +0,0 @@ -- projects_limit = 20 unless local_assigns[:projects_limit] -- avatar = true unless local_assigns[:avatar] == false -- stars = false unless local_assigns[:stars] == true -%ul.well-list.projects-list - - projects.each_with_index do |project, i| - %li{class: (i >= projects_limit) ? 'project-row hide' : 'project-row'} - = render "shared/project", project: project, avatar: avatar, stars: stars - - if projects.blank? - %li - .nothing-here-block There are no projects here. - - if projects.count > projects_limit - %li.bottom - %span.light - #{projects_limit} of #{pluralize(projects.count, 'project')} displayed. - %span - = link_to '#', class: 'js-expand' do - Show all diff --git a/app/views/shared/groups/_group.html.haml b/app/views/shared/groups/_group.html.haml new file mode 100644 index 0000000000000000000000000000000000000000..229ae359bc597bce882dd18b41c2fb0cbcdafd2e --- /dev/null +++ b/app/views/shared/groups/_group.html.haml @@ -0,0 +1,24 @@ +- group_member = local_assigns[:group_member] +%li + - if group_member + .pull-right.hidden-xs + - if can?(current_user, :admin_group, group) + = link_to edit_group_path(group), class: "btn-sm btn btn-grouped" do + %i.fa.fa-cogs + Settings + + = link_to leave_group_group_members_path(group), data: { confirm: leave_group_message(group.name) }, method: :delete, class: "btn-sm btn btn-grouped", title: 'Leave this group' do + %i.fa.fa-sign-out + Leave + + = image_tag group_icon(group), class: "avatar s40 avatar-tile hidden-xs" + = link_to group, class: 'group-name' do + %strong= group.name + + - if group_member + as + %strong #{group_member.human_access} + + %div.light + #{pluralize(group.projects.count, "project")}, #{pluralize(group.users.count, "user")} + diff --git a/app/views/shared/projects/_list.html.haml b/app/views/shared/projects/_list.html.haml new file mode 100644 index 0000000000000000000000000000000000000000..021e3b689a15dacaa597f9b95db5a66a63650dd7 --- /dev/null +++ b/app/views/shared/projects/_list.html.haml @@ -0,0 +1,19 @@ +- projects_limit = 20 unless local_assigns[:projects_limit] +- avatar = true unless local_assigns[:avatar] == false +- stars = true unless local_assigns[:stars] == false + +%ul.projects-list + - projects.each_with_index do |project, i| + - css_class = (i >= projects_limit) ? 'hide' : nil + = render "shared/projects/project", project: project, + avatar: avatar, stars: stars, css_class: css_class + + - if projects.count > projects_limit + %li.bottom.center + .light + #{projects_limit} of #{pluralize(projects.count, 'project')} displayed. + = link_to '#', class: 'js-expand' do + Show all + +:coffeescript + new ProjectsList() diff --git a/app/views/shared/projects/_project.html.haml b/app/views/shared/projects/_project.html.haml new file mode 100644 index 0000000000000000000000000000000000000000..4bfdf4d55ff889fa41f594770efb8113b62d1179 --- /dev/null +++ b/app/views/shared/projects/_project.html.haml @@ -0,0 +1,23 @@ +- avatar = true unless local_assigns[:avatar] == false +- stars = true unless local_assigns[:stars] == false +- css_class = nil unless local_assigns[:css_class] +%li.project-row{ class: css_class } + = cache [project.namespace, project, controller.controller_name, controller.action_name, 'v2'] do + = link_to project_path(project), class: dom_class(project) do + - if avatar + .dash-project-avatar + = project_icon(project, alt: '', class: 'avatar project-avatar s40') + %span.project-full-name + %span.namespace-name + - if project.namespace + = project.namespace.human_name + \/ + %span.project-name.filter-title + = project.name + - if stars + %span.pull-right.light + %i.fa.fa-star + = project.star_count + - if project.description.present? + .project-description + = markdown(project.description, pipeline: :description) diff --git a/app/views/snippets/_snippet.html.haml b/app/views/shared/snippets/_snippet.html.haml similarity index 53% rename from app/views/snippets/_snippet.html.haml rename to app/views/shared/snippets/_snippet.html.haml index 5bb28664349416608c23b1c75db98a4ee406f63e..69a713ad9aacf4b20cae64fbfaca0bbc10e09779 100644 --- a/app/views/snippets/_snippet.html.haml +++ b/app/views/shared/snippets/_snippet.html.haml @@ -1,12 +1,12 @@ -%li - %h4.snippet-title +%li.snippet-row + .snippet-title = link_to reliable_snippet_path(snippet) do = truncate(snippet.title, length: 60) - if snippet.private? %span.label.label-gray %i.fa.fa-lock private - %span.cgray.monospace.tiny.pull-right + %span.monospace.pull-right = snippet.file_name %small.pull-right.cgray @@ -14,10 +14,8 @@ = link_to snippet.project.name_with_namespace, namespace_project_path(snippet.project.namespace, snippet.project) .snippet-info - = "##{snippet.id}" - %span - by - = link_to user_snippets_path(snippet.author) do - = image_tag avatar_icon(snippet.author_email), class: "avatar avatar-inline s16", alt: '' - = snippet.author_name - %span.light #{time_ago_with_tooltip(snippet.created_at)} + = link_to user_snippets_path(snippet.author) do + = image_tag avatar_icon(snippet.author_email), class: "avatar s24", alt: '' + = snippet.author_name + authored #{time_ago_with_tooltip(snippet.created_at)} + diff --git a/app/views/snippets/_snippets.html.haml b/app/views/snippets/_snippets.html.haml index 40df42b6cf5805d73d67165769621f8528105eec..d9aa4dd1d2eb22db73e91a8f8e98cad288474197 100644 --- a/app/views/snippets/_snippets.html.haml +++ b/app/views/snippets/_snippets.html.haml @@ -1,5 +1,5 @@ %ul.bordered-list - = render partial: 'snippet', collection: @snippets + = render partial: 'shared/snippets/snippet', collection: @snippets - if @snippets.empty? %li .nothing-here-block Nothing here. diff --git a/app/views/users/_projects.html.haml b/app/views/users/_projects.html.haml index 297fa53739407271eb9303bb51c9ce827ce59d45..a126a858ea85f0ce96e785dc2ebc0297a161d38f 100644 --- a/app/views/users/_projects.html.haml +++ b/app/views/users/_projects.html.haml @@ -1,13 +1,13 @@ - if local_assigns.has_key?(:contributed_projects) && contributed_projects.present? .panel.panel-default.contributed-projects .panel-heading Projects contributed to - = render 'shared/projects_list', + = render 'shared/projects/list', projects: contributed_projects.sort_by(&:star_count).reverse, projects_limit: 5, stars: true, avatar: false - if local_assigns.has_key?(:projects) && projects.present? .panel.panel-default .panel-heading Personal projects - = render 'shared/projects_list', + = render 'shared/projects/list', projects: projects.sort_by(&:star_count).reverse, projects_limit: 10, stars: true, avatar: false 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 0000000000000000000000000000000000000000..093c068fbde7ecee87d1e7cc978cacfebfc37794 --- /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 108c48bf321cf6d6456635f231e26a562ac641af..7ee1c6e214681a647f3de09cbd89d7f9946e7085 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20150818213832) do +ActiveRecord::Schema.define(version: 20150824002011) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -566,13 +566,14 @@ ActiveRecord::Schema.define(version: 20150818213832) 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.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/features/admin/hooks.feature b/features/admin/hooks.feature new file mode 100644 index 0000000000000000000000000000000000000000..5ca332d9f1cfe031041697267cfa703759205c2a --- /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/project/hooks.feature b/features/project/hooks.feature index 1a60846a23e6eb79e020324699fbb6c9c76709d1..627738004c4afcbd2df16758fc5ba32094c4efaf 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 0000000000000000000000000000000000000000..541e25fcb703fdb955926c082d7807841a4ad8d7 --- /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/hooks.rb b/features/steps/project/hooks.rb index 04e3bf78ede53b0080c55dac3653cb49a4a28e37..df4a23a37169a5759a18e842980100b214518110 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'