Commit 4ea85da9 authored by DJ Mountney's avatar DJ Mountney

Merge remote-tracking branch 'dev/master'

parents f5bc48cf 7be39a89
......@@ -2,6 +2,11 @@
documentation](doc/development/changelog.md) for instructions on adding your own
entry.
## 8.17.4 (2017-03-19)
- Only show public emails in atom feeds.
- To protect against Server-side Request Forgery project import URLs are now prohibited against localhost or the server IP except for the assigned instance URL and port. Imports are also prohibited from ports below 1024 with the exception of ports 22, 80, and 443.
## 8.17.3 (2017-03-07)
- Fix the redirect to custom home page URL. !9518
......@@ -210,6 +215,11 @@ entry.
- Remove deprecated GitlabCiService.
- Requeue pending deletion projects.
## 8.16.8 (2017-03-19)
- Only show public emails in atom feeds.
- To protect against Server-side Request Forgery project import URLs are now prohibited against localhost or the server IP except for the assigned instance URL and port. Imports are also prohibited from ports below 1024 with the exception of ports 22, 80, and 443.
## 8.16.7 (2017-02-27)
- No changes.
......@@ -411,6 +421,11 @@ entry.
- Add margin to markdown math blocks.
- Add hover state to MR comment reply button.
## 8.15.8 (2017-03-19)
- Only show public emails in atom feeds.
- To protect against Server-side Request Forgery project import URLs are now prohibited against localhost or the server IP except for the assigned instance URL and port. Imports are also prohibited from ports below 1024 with the exception of ports 22, 80, and 443.
## 8.15.7 (2017-02-15)
- No changes.
......
......@@ -14,6 +14,7 @@ export default {
class="btn external_url"
:href="externalUrl"
target="_blank"
rel="noopener noreferrer"
title="Environment external URL">
<i class="fa fa-external-link" aria-hidden="true"></i>
</a>
......
......@@ -14,13 +14,13 @@ import MiniPipelineGraph from './mini_pipeline_graph_dropdown';
<%= ci_success_icon %>
<span>
Deployed to
<a href="<%- url %>" target="_blank" class="environment">
<a href="<%- url %>" target="_blank" rel="noopener noreferrer" class="environment">
<%- name %>
</a>
<span class="js-environment-timeago" data-toggle="tooltip" data-placement="top" data-title="<%- deployed_at_formatted %>">
<%- deployed_at %>
</span>
<a class="js-environment-link" href="<%- external_url %>" target="_blank">
<a class="js-environment-link" href="<%- external_url %>" target="_blank" rel="noopener noreferrer">
<i class="fa fa-external-link"></i>
View on <%- external_url_formatted %>
</a>
......
......@@ -148,7 +148,7 @@ class Projects::IssuesController < Projects::ApplicationController
end
format.json do
render json: @issue.to_json(include: { milestone: {}, assignee: { methods: :avatar_url }, labels: { methods: :text_color } }, methods: [:task_status, :task_status_short])
render json: @issue.to_json(include: { milestone: {}, assignee: { only: [:name, :username], methods: [:avatar_url] }, labels: { methods: :text_color } }, methods: [:task_status, :task_status_short])
end
end
......
......@@ -308,7 +308,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
end
format.json do
render json: @merge_request.to_json(include: { milestone: {}, assignee: { methods: :avatar_url }, labels: { methods: :text_color } }, methods: [:task_status, :task_status_short])
render json: @merge_request.to_json(include: { milestone: {}, assignee: { only: [:name, :username], methods: [:avatar_url] }, labels: { methods: :text_color } }, methods: [:task_status, :task_status_short])
end
end
rescue ActiveRecord::StaleObjectError
......
......@@ -215,6 +215,6 @@ module BlobHelper
end
def open_raw_file_button(path)
link_to icon('file-code-o'), path, class: 'btn btn-sm has-tooltip', target: '_blank', title: 'Open raw', data: { container: 'body' }
link_to icon('file-code-o'), path, class: 'btn btn-sm has-tooltip', target: '_blank', rel: 'noopener noreferrer', title: 'Open raw', data: { container: 'body' }
end
end
......@@ -211,7 +211,7 @@ module CommitsHelper
external_url = environment.external_url_for(diff_new_path, commit_sha)
return unless external_url
link_to(external_url, class: 'btn btn-file-option has-tooltip', target: '_blank', title: "View on #{environment.formatted_external_url}", data: { container: 'body' }) do
link_to(external_url, class: 'btn btn-file-option has-tooltip', target: '_blank', rel: 'noopener noreferrer', title: "View on #{environment.formatted_external_url}", data: { container: 'body' }) do
icon('external-link')
end
end
......
......@@ -7,7 +7,7 @@ module ImportHelper
def provider_project_link(provider, path_with_namespace)
url = __send__("#{provider}_project_url", path_with_namespace)
link_to path_with_namespace, url, target: '_blank'
link_to path_with_namespace, url, target: '_blank', rel: 'noopener noreferrer'
end
private
......
......@@ -48,11 +48,13 @@ module Issuable
delegate :name,
:email,
:public_email,
to: :author,
prefix: true
delegate :name,
:email,
:public_email,
to: :assignee,
allow_nil: true,
prefix: true
......
......@@ -16,7 +16,7 @@ class Event < ActiveRecord::Base
RESET_PROJECT_ACTIVITY_INTERVAL = 1.hour
delegate :name, :email, to: :author, prefix: true, allow_nil: true
delegate :name, :email, :public_email, to: :author, prefix: true, allow_nil: true
delegate :title, to: :issue, prefix: true, allow_nil: true
delegate :title, to: :merge_request, prefix: true, allow_nil: true
delegate :title, to: :note, prefix: true, allow_nil: true
......
......@@ -196,6 +196,7 @@ class Project < ActiveRecord::Base
validates :name, uniqueness: { scope: :namespace_id }
validates :path, uniqueness: { scope: :namespace_id }
validates :import_url, addressable_url: true, if: :external_import?
validates :import_url, importable_url: true, if: [:external_import?, :import_url_changed?]
validates :star_count, numericality: { greater_than_or_equal_to: 0 }
validate :check_limit, on: :create
validate :avatar_type,
......
......@@ -33,6 +33,7 @@ module Projects
def import_repository
begin
raise Error, "Blocked import URL." if Gitlab::UrlBlocker.blocked_url?(project.import_url)
gitlab_shell.import_repository(project.repository_storage_path, project.path_with_namespace, project.import_url)
rescue => e
# Expire cache to prevent scenarios such as:
......@@ -40,7 +41,7 @@ module Projects
# 2. Retried import, repo is broken or not imported but +exists?+ still returns true
project.repository.before_import if project.repository_exists?
raise Error, "Error importing repository #{project.import_url} into #{project.path_with_namespace} - #{e.message}"
raise Error, "Error importing repository #{project.import_url} into #{project.path_with_namespace} - #{e.message}"
end
end
......
# ImportableUrlValidator
#
# This validator blocks projects from using dangerous import_urls to help
# protect against Server-side Request Forgery (SSRF).
class ImportableUrlValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value)
if Gitlab::UrlBlocker.blocked_url?(value)
record.errors.add(attribute, "imports are not allowed from that URL")
end
end
end
......@@ -48,7 +48,7 @@
.form-actions
= f.submit 'Save', class: 'btn btn-save append-right-10'
- if @appearance.persisted?
= link_to 'Preview last save', preview_admin_appearances_path, class: 'btn', target: '_blank'
= link_to 'Preview last save', preview_admin_appearances_path, class: 'btn', target: '_blank', rel: 'noopener noreferrer'
- if @appearance.updated_at
%span.pull-right
......
......@@ -404,7 +404,7 @@
Enable Sentry
.help-block
Sentry is an error reporting and logging tool which is currently not shipped with GitLab, get it here:
%a{ href: 'https://getsentry.com', target: '_blank' } https://getsentry.com
%a{ href: 'https://getsentry.com', target: '_blank', rel: 'noopener noreferrer' } https://getsentry.com
.form-group
= f.label :sentry_dsn, 'Sentry DSN', class: 'control-label col-sm-2'
......
......@@ -9,7 +9,7 @@ xml.entry do
xml.author do
xml.name event.author_name
xml.email event.author_email
xml.email event.author_public_email
end
xml.summary(type: "xhtml") do |summary|
......
......@@ -15,6 +15,6 @@
= link_to note.attachment.url, target: '_blank' do
= image_tag note.attachment.url, class: 'note-image-attach'
- else
= link_to note.attachment.url, target: "_blank", class: 'note-file-attach' do
= link_to note.attachment.url, target: '_blank', class: 'note-file-attach' do
%i.fa.fa-paperclip
= note.attachment_identifier
......@@ -17,7 +17,7 @@
%br
Used by more than 100,000 organizations, GitLab is the most popular solution to manage git repositories on-premises.
%br
Read more about GitLab at #{link_to promo_host, promo_url, target: '_blank'}.
Read more about GitLab at #{link_to promo_host, promo_url, target: '_blank', rel: 'noopener noreferrer'}.
- if current_application_settings.help_page_text.present?
%hr
= markdown_field(current_application_settings, :help_page_text)
......
......@@ -33,7 +33,7 @@
- @already_added_projects.each do |project|
%tr{ id: "project_#{project.id}", class: "#{project_status_css_class(project.import_status)}" }
%td
= link_to project.import_source, "https://bitbucket.org/#{project.import_source}", target: '_blank'
= link_to project.import_source, "https://bitbucket.org/#{project.import_source}", target: '_blank', rel: 'noopener noreferrer'
%td
= link_to project.path_with_namespace, [project.namespace.becomes(Namespace), project]
%td.job-status
......@@ -50,7 +50,7 @@
- @repos.each do |repo|
%tr{ id: "repo_#{repo.owner}___#{repo.slug}" }
%td
= link_to repo.full_name, "https://bitbucket.org/#{repo.full_name}", target: "_blank"
= link_to repo.full_name, "https://bitbucket.org/#{repo.full_name}", target: '_blank', rel: 'noopener noreferrer'
%td.import-target
%fieldset.row
.input-group
......@@ -70,7 +70,7 @@
- @incompatible_repos.each do |repo|
%tr{ id: "repo_#{repo.owner}___#{repo.slug}" }
%td
= link_to repo.full_name, "https://bitbucket.org/#{repo.full_name}", target: '_blank'
= link_to repo.full_name, "https://bitbucket.org/#{repo.full_name}", target: '_blank', rel: 'noopener noreferrer'
%td.import-target
%td.import-actions-job-status
= label_tag 'Incompatible Project', nil, class: 'label label-danger'
......
......@@ -43,7 +43,7 @@
- @repos.each do |repo|
%tr{ id: "repo_#{repo["id"]}" }
%td
= link_to repo["path_with_namespace"], "https://gitlab.com/#{repo["path_with_namespace"]}", target: "_blank"
= link_to repo["path_with_namespace"], "https://gitlab.com/#{repo["path_with_namespace"]}", target: "_blank", rel: 'noopener noreferrer'
%td.import-target
= import_project_target(repo['namespace']['path'], repo['name'])
%td.import-actions.job-status
......
......@@ -13,7 +13,7 @@
%li
%p
Go to
#{link_to "Google Takeout", "https://www.google.com/settings/takeout", target: "_blank"}.
#{link_to "Google Takeout", "https://www.google.com/settings/takeout", target: '_blank', rel: 'noopener noreferrer'}.
%li
%p
Make sure you're logged into the account that owns the projects you'd like to import.
......
......@@ -36,7 +36,7 @@
- @already_added_projects.each do |project|
%tr{ id: "project_#{project.id}", class: "#{project_status_css_class(project.import_status)}" }
%td
= link_to project.import_source, "https://code.google.com/p/#{project.import_source}", target: "_blank"
= link_to project.import_source, "https://code.google.com/p/#{project.import_source}", target: "_blank", rel: 'noopener noreferrer'
%td
= link_to project.path_with_namespace, [project.namespace.becomes(Namespace), project]
%td.job-status
......@@ -53,7 +53,7 @@
- @repos.each do |repo|
%tr{ id: "repo_#{repo.id}" }
%td
= link_to repo.name, "https://code.google.com/p/#{repo.name}", target: "_blank"
= link_to repo.name, "https://code.google.com/p/#{repo.name}", target: "_blank", rel: 'noopener noreferrer'
%td.import-target
#{current_user.username}/#{repo.name}
%td.import-actions.job-status
......@@ -63,7 +63,7 @@
- @incompatible_repos.each do |repo|
%tr{ id: "repo_#{repo.id}" }
%td
= link_to repo.name, "https://code.google.com/p/#{repo.name}", target: "_blank"
= link_to repo.name, "https://code.google.com/p/#{repo.name}", target: "_blank", rel: 'noopener noreferrer'
%td.import-target
%td.import-actions-job-status
= label_tag "Incompatible Project", nil, class: "label label-danger"
......
......@@ -7,7 +7,7 @@ xml.entry do
xml.author do
xml.name issue.author_name
xml.email issue.author_email
xml.email issue.author_public_email
end
xml.summary issue.title
......@@ -26,7 +26,7 @@ xml.entry do
if issue.assignee
xml.assignee do
xml.name issue.assignee.name
xml.email issue.assignee.email
xml.email issue.assignee_public_email
end
end
end
......@@ -2,5 +2,5 @@
%p
= icon('circle', class: 'cgreen')
Integration is active for
= link_to koding_project_url, target: '_blank' do
= link_to koding_project_url, target: '_blank', rel: 'noopener noreferrer' do
#{current_application_settings.koding_url}
......@@ -18,7 +18,7 @@
or change it at #{link_to Gitlab.config.gravatar.host, "http://" + Gitlab.config.gravatar.host}
.col-lg-9
.clearfix.avatar-image.append-bottom-default
= link_to avatar_icon(@user, 400), target: '_blank' do
= link_to avatar_icon(@user, 400), target: '_blank', rel: 'noopener noreferrer' do
= image_tag avatar_icon(@user, 160), alt: '', class: 'avatar s160'
%h5.prepend-top-0
Upload new avatar
......
......@@ -9,7 +9,7 @@
- else
.nothing-here-block
The SVG could not be displayed as it is too large, you can
#{link_to('view the raw file', namespace_project_raw_path(@project.namespace, @project, @id), target: '_blank')}
#{link_to('view the raw file', namespace_project_raw_path(@project.namespace, @project, @id), target: '_blank', rel: 'noopener noreferrer')}
instead.
- else
%img{ src: namespace_project_raw_path(@project.namespace, @project, tree_join(@commit.id, blob.path)), alt: "#{blob.name}" }
......@@ -3,7 +3,7 @@
.nothing-here-block
File too large, you can
= succeed '.' do
= link_to 'view the raw file', namespace_project_raw_path(@project.namespace, @project, @id), target: '_blank'
= link_to 'view the raw file', namespace_project_raw_path(@project.namespace, @project, @id), target: '_blank', rel: 'noopener noreferrer'
- else
- blob.load_all_data!(@repository)
......
......@@ -9,7 +9,7 @@
- if @conflict
.alert.alert-danger
Someone edited the file the same time you did. Please check out
= link_to "the file", namespace_project_blob_path(@project.namespace, @project, tree_join(@target_branch, @file_path)), target: "_blank"
= link_to "the file", namespace_project_blob_path(@project.namespace, @project, tree_join(@target_branch, @file_path)), target: "_blank", rel: 'noopener noreferrer'
and make sure your changes will not unintentionally remove theirs.
.file-editor
......
- if koding_enabled? && current_user && @repository.koding_yml && can_push_branch?(@project, @project.default_branch)
= link_to koding_project_url(@project), class: 'btn project-action-button inline', target: '_blank' do
= link_to koding_project_url(@project), class: 'btn project-action-button inline', target: '_blank', rel: 'noopener noreferrer' do
Run in IDE (Koding)
......@@ -9,7 +9,7 @@
Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project.
To set up CA, you must first define a production environment by setting up your CI and then deploy to production.
%p
%a.btn{ href: help_page_path('user/project/cycle_analytics'), target: "_blank" } Read more
%a.btn{ href: help_page_path('user/project/cycle_analytics'), target: '_blank' } Read more
.col-md-6.overview-image
%span.overview-icon
= custom_icon ('icon_cycle_analytics_overview')
- if environment.external_url && can?(current_user, :read_environment, environment)
= link_to environment.external_url, target: '_blank', class: 'btn external-url' do
= link_to environment.external_url, target: '_blank', rel: 'noopener noreferrer', class: 'btn external-url' do
= icon('external-link')
......@@ -16,7 +16,7 @@
.pull-right
- if @merge_request.source_branch_exists?
- if koding_enabled? && @repository.koding_yml
= link_to koding_project_url(@merge_request.source_project, @merge_request.source_branch, @merge_request.commits.first.short_id), class: "btn inline btn-grouped btn-sm", target: '_blank' do
= link_to koding_project_url(@merge_request.source_project, @merge_request.source_branch, @merge_request.commits.first.short_id), class: "btn inline btn-grouped btn-sm", target: '_blank', rel: 'noopener noreferrer' do
Run in IDE (Koding)
= link_to "#modal_merge_info", class: "btn inline btn-grouped btn-sm", "data-toggle" => "modal" do
Check out branch
......
......@@ -49,7 +49,7 @@
%strong Tip:
= succeed '.' do
You can also checkout merge requests locally by
= link_to 'following these guidelines', help_page_path('user/project/merge_requests.md', anchor: "checkout-merge-requests-locally"), target: '_blank'
= link_to 'following these guidelines', help_page_path('user/project/merge_requests.md', anchor: "checkout-merge-requests-locally"), target: '_blank', rel: 'noopener noreferrer'
:javascript
$(function(){
......
......@@ -4,13 +4,13 @@
%ul.list-unstyled.indent-list
%li
1.
= link_to 'https://docs.mattermost.com/developer/slash-commands.html#enabling-custom-commands', target: '_blank', rel: 'noreferrer noopener nofollow' do
= link_to 'https://docs.mattermost.com/developer/slash-commands.html#enabling-custom-commands', target: '_blank', rel: 'noopener noreferrer nofollow' do
Enable custom slash commands
= icon('external-link')
on your Mattermost installation
%li
2.
= link_to 'https://docs.mattermost.com/developer/slash-commands.html#set-up-a-custom-command', target: '_blank', rel: 'noreferrer noopener nofollow' do
= link_to 'https://docs.mattermost.com/developer/slash-commands.html#set-up-a-custom-command', target: '_blank', rel: 'noopener noreferrer nofollow' do
Add a slash command
= icon('external-link')
in your Mattermost team with these options:
......
......@@ -4,7 +4,7 @@
%p
This service allows users to perform common operations on this
project by entering slash commands in Mattermost.
= link_to help_page_path('user/project/integrations/mattermost_slash_commands.md'), target: '_blank', ref: 'noreferrer nofollow noopener' do
= link_to help_page_path('user/project/integrations/mattermost_slash_commands.md'), target: '_blank' do
View documentation
= icon('external-link')
%p.inline
......
......@@ -5,7 +5,7 @@
%p
This service allows users to perform common operations on this
project by entering slash commands in Slack.
= link_to help_page_path('user/project/integrations/slack_slash_commands.md'), target: '_blank', ref: 'noreferrer nofollow noopener' do
= link_to help_page_path('user/project/integrations/slack_slash_commands.md'), target: '_blank' do
View documentation
= icon('external-link')
%p.inline
......@@ -57,7 +57,7 @@
= label_tag nil, 'Customize icon', class: 'col-sm-2 col-xs-12 control-label'
.col-sm-10.col-xs-12.text-block
= image_tag(asset_url('slash-command-logo.png'), width: 36, height: 36)
= link_to('Download image', asset_url('gitlab_logo.png'), class: 'btn btn-sm', target: '_blank')
= link_to('Download image', asset_url('gitlab_logo.png'), class: 'btn btn-sm', target: '_blank', rel: 'noopener noreferrer')
.form-group
= label_tag nil, 'Autocomplete', class: 'col-sm-2 col-xs-12 control-label'
......
......@@ -8,7 +8,7 @@
.alert.alert-danger
Someone edited the #{issuable.class.model_name.human.downcase} the same time you did.
Please check out
= link_to "the #{issuable.class.model_name.human.downcase}", polymorphic_path([@project.namespace.becomes(Namespace), @project, issuable]), target: "_blank"
= link_to "the #{issuable.class.model_name.human.downcase}", polymorphic_path([@project.namespace.becomes(Namespace), @project, issuable]), target: "_blank", rel: 'noopener noreferrer'
and make sure your changes will not unintentionally remove theirs
.form-group
......
......@@ -33,7 +33,7 @@
.profile-header
.avatar-holder
= link_to avatar_icon(@user, 400), target: '_blank' do
= link_to avatar_icon(@user, 400), target: '_blank', rel: 'noopener noreferrer' do
= image_tag avatar_icon(@user, 90), class: "avatar s90", alt: ''
.user-info
......
---
title: Only show public emails in atom feeds
merge_request:
author:
---
title: To protect against Server-side Request Forgery project import URLs are now prohibited against localhost or the server IP except for the assigned instance URL and port. Imports are also prohibited from ports below 1024 with the exception of ports 22, 80, and 443.
merge_request:
author:
......@@ -2,7 +2,6 @@ module Banzai
module Filter
# HTML filter that wraps links around inline images.
class ImageLinkFilter < HTML::Pipeline::Filter
# Find every image that isn't already wrapped in an `a` tag, create
# a new node (a link to the image source), copy the image as a child
# of the anchor, and then replace the img with the link-wrapped version.
......@@ -12,7 +11,8 @@ module Banzai
'a',
class: 'no-attachment-icon',
href: img['src'],
target: '_blank'
target: '_blank',
rel: 'noopener noreferrer'
)
link.children = img.clone
......
......@@ -43,6 +43,7 @@ module Banzai
element['title'] || element['alt'],
href: element['src'],
target: '_blank',
rel: 'noopener noreferrer',
title: "Download '#{element['title'] || element['alt']}'")
download_paragraph = doc.document.create_element('p')
download_paragraph.children = link
......
require 'resolv'
module Gitlab
class UrlBlocker
class << self
# Used to specify what hosts and port numbers should be prohibited for project
# imports.
VALID_PORTS = [22, 80, 443].freeze
def blocked_url?(url)
return false if url.nil?
blocked_ips = ["127.0.0.1", "::1", "0.0.0.0"]
blocked_ips.concat(Socket.ip_address_list.map(&:ip_address))
begin
uri = Addressable::URI.parse(url)
# Allow imports from the GitLab instance itself but only from the configured ports
return false if internal?(uri)
return true if blocked_port?(uri.port)
server_ips = Resolv.getaddresses(uri.hostname)
return true if (blocked_ips & server_ips).any?
rescue Addressable::URI::InvalidURIError
return true
end
false
end
private
def blocked_port?(port)
return false if port.blank?
port < 1024 && !VALID_PORTS.include?(port)
end
def internal?(uri)
internal_web?(uri) || internal_shell?(uri)
end
def internal_web?(uri)
uri.hostname == config.gitlab.host &&
(uri.port.blank? || uri.port == config.gitlab.port)
end
def internal_shell?(uri)
uri.hostname == config.gitlab_shell.ssh_host &&
(uri.port.blank? || uri.port == config.gitlab_shell.ssh_port)
end
def config
Gitlab.config
end
end
end
end
......@@ -152,6 +152,24 @@ describe Projects::IssuesController do
it_behaves_like 'update invalid issuable', Issue
context 'changing the assignee' do
it 'limits the attributes exposed on the assignee' do
assignee = create(:user)
project.add_developer(assignee)
put :update,
namespace_id: project.namespace.to_param,
project_id: project,
id: issue.iid,
issue: { assignee_id: assignee.id },
format: :json
body = JSON.parse(response.body)
expect(body['assignee'].keys)
.to match_array(%w(name username avatar_url))
end
end
context 'when moving issue to another private project' do
let(:another_project) { create(:empty_project, :private) }
......
......@@ -203,6 +203,24 @@ describe Projects::MergeRequestsController do
end
describe 'PUT update' do
context 'changing the assignee' do
it 'limits the attributes exposed on the assignee' do
assignee = create(:user)
project.add_developer(assignee)
put :update,
namespace_id: project.namespace.to_param,
project_id: project,
id: merge_request.iid,
merge_request: { assignee_id: assignee.id },
format: :json
body = JSON.parse(response.body)
expect(body['assignee'].keys)
.to match_array(%w(name username avatar_url))
end
end
context 'there is no source project' do
let(:project) { create(:project) }
let(:fork_project) { create(:forked_project_with_submodules) }
......
......@@ -2,7 +2,8 @@ require 'spec_helper'
describe "Dashboard Issues Feed", feature: true do
describe "GET /issues" do
let!(:user) { create(:user) }
let!(:user) { create(:user, email: 'private1@example.com', public_email: 'public1@example.com') }
let!(:assignee) { create(:user, email: 'private2@example.com', public_email: 'public2@example.com') }
let!(:project1) { create(:project) }
let!(:project2) { create(:project) }
......@@ -31,7 +32,7 @@ describe "Dashboard Issues Feed", feature: true do
end
context "issue with basic fields" do
let!(:issue2) { create(:issue, author: user, assignee: user, project: project2, description: 'test desc') }
let!(:issue2) { create(:issue, author: user, assignee: assignee, project: project2, description: 'test desc') }
it "renders issue fields" do
visit issues_dashboard_path(:atom, private_token: user.private_token)
......@@ -39,8 +40,8 @@ describe "Dashboard Issues Feed", feature: true do
entry = find(:xpath, "//feed/entry[contains(summary/text(),'#{issue2.title}')]")
expect(entry).to be_present
expect(entry).to have_selector('author email', text: issue2.author_email)
expect(entry).to have_selector('assignee email', text: issue2.author_email)
expect(entry).to have_selector('author email', text: issue2.author_public_email)
expect(entry).to have_selector('assignee email', text: issue2.assignee_public_email)
expect(entry).not_to have_selector('labels')
expect(entry).not_to have_selector('milestone')
expect(entry).to have_selector('description', text: issue2.description)
......@@ -50,7 +51,7 @@ describe "Dashboard Issues Feed", feature: true do
context "issue with label and milestone" do
let!(:milestone1) { create(:milestone, project: project1, title: 'v1') }
let!(:label1) { create(:label, project: project1, title: 'label1') }
let!(:issue1) { create(:issue, author: user, assignee: user, project: project1, milestone: milestone1) }
let!(:issue1) { create(:issue, author: user, assignee: assignee, project: project1, milestone: milestone1) }
before do
issue1.labels << label1
......@@ -62,8 +63,8 @@ describe "Dashboard Issues Feed", feature: true do
entry = find(:xpath, "//feed/entry[contains(summary/text(),'#{issue1.title}')]")
expect(entry).to be_present
expect(entry).to have_selector('author email', text: issue1.author_email)
expect(entry).to have_selector('assignee email', text: issue1.author_email)
expect(entry).to have_selector('author email', text: issue1.author_public_email)
expect(entry).to have_selector('assignee email', text: issue1.assignee_public_email)
expect(entry).to have_selector('labels label', text: label1.title)
expect(entry).to have_selector('milestone', text: milestone1.title)
expect(entry).not_to have_selector('description')
......
......@@ -2,10 +2,11 @@ require 'spec_helper'
describe 'Issues Feed', feature: true do
describe 'GET /issues' do
let!(:user) { create(:user) }
let!(:user) { create(:user, email: 'private1@example.com', public_email: 'public1@example.com') }
let!(:assignee) { create(:user, email: 'private2@example.com', public_email: 'public2@example.com') }
let!(:group) { create(:group) }
let!(:project) { create(:project) }
let!(:issue) { create(:issue, author: user, project: project) }
let!(:issue) { create(:issue, author: user, assignee: assignee, project: project) }
before do
project.team << [user, :developer]
......@@ -20,7 +21,8 @@ describe 'Issues Feed', feature: true do
expect(response_headers['Content-Type']).
to have_content('application/atom+xml')
expect(body).to have_selector('title', text: "#{project.name} issues")
expect(body).to have_selector('author email', text: issue.author_email)
expect(body).to have_selector('author email', text: issue.author_public_email)
expect(body).to have_selector('assignee email', text: issue.author_public_email)
expect(body).to have_selector('entry summary', text: issue.title)
end
end
......@@ -33,7 +35,8 @@ describe 'Issues Feed', feature: true do
expect(response_headers['Content-Type']).
to have_content('application/atom+xml')
expect(body).to have_selector('title', text: "#{project.name} issues")
expect(body).to have_selector('author email', text: issue.author_email)
expect(body).to have_selector('author email', text: issue.author_public_email)
expect(body).to have_selector('assignee email', text: issue.author_public_email)
expect(body).to have_selector('entry summary', text: issue.title)
end
end
......
require 'spec_helper'
describe Gitlab::UrlBlocker, lib: true do
describe '#blocked_url?' do
it 'allows imports from configured web host and port' do
import_url = "http://#{Gitlab.config.gitlab.host}:#{Gitlab.config.gitlab.port}/t.git"
expect(described_class.blocked_url?(import_url)).to be false
end
it 'allows imports from configured SSH host and port' do
import_url = "http://#{Gitlab.config.gitlab_shell.ssh_host}:#{Gitlab.config.gitlab_shell.ssh_port}/t.git"
expect(described_class.blocked_url?(import_url)).to be false
end
it 'returns true for bad localhost hostname' do
expect(described_class.blocked_url?('https://localhost:65535/foo/foo.git')).to be true
end
it 'returns true for bad port' do
expect(described_class.blocked_url?('https://gitlab.com:25/foo/foo.git')).to be true
end
it 'returns true for invalid URL' do
expect(described_class.blocked_url?('http://:8080')).to be true
end
it 'returns false for legitimate URL' do
expect(described_class.blocked_url?('https://gitlab.com/foo/foo.git')).to be false
end
end
end
......@@ -218,6 +218,20 @@ describe Project, models: true do
expect(project2.import_data).to be_nil
end
it "does not allow blocked import_url localhost" do
project2 = build(:empty_project, import_url: 'http://localhost:9000/t.git')
expect(project2).to be_invalid
expect(project2.errors[:import_url]).to include('imports are not allowed from that URL')
end
it "does not allow blocked import_url port" do
project2 = build(:empty_project, import_url: 'http://github.com:25/t.git')
expect(project2).to be_invalid
expect(project2.errors[:import_url]).to include('imports are not allowed from that URL')
end
describe 'project pending deletion' do
let!(:project_pending_deletion) do
create(:empty_project,
......
......@@ -120,6 +120,26 @@ describe Projects::ImportService, services: true do
end
end
context 'with blocked import_URL' do
it 'fails with localhost' do
project.import_url = 'https://localhost:9000/vim/vim.git'
result = described_class.new(project, user).execute
expect(result[:status]).to eq :error
expect(result[:message]).to end_with 'Blocked import URL.'
end
it 'fails with port 25' do
project.import_url = "https://github.com:25/vim/vim.git"
result = described_class.new(project, user).execute
expect(result[:status]).to eq :error
expect(result[:message]).to end_with 'Blocked import URL.'
end
end
def stub_github_omniauth_provider
provider = OpenStruct.new(
'name' => 'github',
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment