Commit ad55f0d6 authored by Douwe Maan's avatar Douwe Maan

Merge branch 'master' into comment-updated-by

parents 8b6ae010 4b7c2f0b
Please view this file on the master branch, on stable branches it's out of date. Please view this file on the master branch, on stable branches it's out of date.
v 7.14.0 (unreleased) v 7.14.0 (unreleased)
- Fix coloring of diffs on MR Discussion-tab (Gert Goet)
- Fix "Network" and "Graphs" pages for branches with encoded slashes (Stan Hu) - Fix "Network" and "Graphs" pages for branches with encoded slashes (Stan Hu)
- Fix errors deleting and creating branches with encoded slashes (Stan Hu) - Fix errors deleting and creating branches with encoded slashes (Stan Hu)
- Always add current user to autocomplete controller to support filter by "Me" (Stan Hu)
- Fix multi-line syntax highlighting (Stan Hu) - Fix multi-line syntax highlighting (Stan Hu)
- Fix network graph when branch name has single quotes (Stan Hu) - Fix network graph when branch name has single quotes (Stan Hu)
- Add "Confirm user" button in user admin page (Stan Hu) - Add "Confirm user" button in user admin page (Stan Hu)
...@@ -39,6 +41,10 @@ v 7.14.0 (unreleased) ...@@ -39,6 +41,10 @@ v 7.14.0 (unreleased)
- Remove satellites - Remove satellites
- Remove comments and email addresses when publicly exposing ssh keys (Zeger-Jan van de Weg) - Remove comments and email addresses when publicly exposing ssh keys (Zeger-Jan van de Weg)
v 7.13.3
- Fix bug causing Bitbucket importer to crash when OAuth application had been removed.
- Allow users to send abuse reports
v 7.13.2 v 7.13.2
- Fix randomly failed spec - Fix randomly failed spec
- Create project services on Project creation - Create project services on Project creation
......
...@@ -48,6 +48,10 @@ ...@@ -48,6 +48,10 @@
display: block; display: block;
} }
.project-home-desc {
font-size: 21px;
}
.project-repo-buttons, .project-repo-buttons,
.git-clone-holder { .git-clone-holder {
display: none; display: none;
......
...@@ -30,7 +30,13 @@ ...@@ -30,7 +30,13 @@
} }
} }
.lead { .project-home-desc {
h1 {
margin: 0;
margin-bottom: 10px;
font-size: 26px;
}
p { p {
display: inline; display: inline;
} }
......
class AbuseReportsController < ApplicationController
def new
@abuse_report = AbuseReport.new
@abuse_report.user_id = params[:user_id]
end
def create
@abuse_report = AbuseReport.new(report_params)
@abuse_report.reporter = current_user
if @abuse_report.save
message = "Thank you for your report. A GitLab administrator will look into it shortly."
redirect_to root_path, notice: message
else
render :new
end
end
private
def report_params
params.require(:abuse_report).permit(:user_id, :message)
end
end
class Admin::AbuseReportsController < Admin::ApplicationController
def index
@abuse_reports = AbuseReport.order(id: :desc).page(params[:page])
end
def destroy
AbuseReport.find(params[:id]).destroy
redirect_to admin_abuse_reports_path, notice: 'Report was removed'
end
end
...@@ -33,6 +33,8 @@ class AutocompleteController < ApplicationController ...@@ -33,6 +33,8 @@ class AutocompleteController < ApplicationController
@users = @users.search(params[:search]) if params[:search].present? @users = @users.search(params[:search]) if params[:search].present?
@users = @users.active @users = @users.active
@users = @users.page(params[:page]).per(PER_PAGE) @users = @users.page(params[:page]).per(PER_PAGE)
# Always include current user if available to filter by "Me"
@users = User.find(@users.pluck(:id) + [current_user.id]).uniq if current_user
render json: @users, only: [:name, :username, :id], methods: [:avatar_url] render json: @users, only: [:name, :username, :id], methods: [:avatar_url]
end end
......
class AbuseReport < ActiveRecord::Base
belongs_to :reporter, class_name: "User"
belongs_to :user
validates :reporter, presence: true
validates :user, presence: true
validates :message, presence: true
validates :user_id, uniqueness: { scope: :reporter_id }
end
...@@ -114,6 +114,9 @@ class Namespace < ActiveRecord::Base ...@@ -114,6 +114,9 @@ class Namespace < ActiveRecord::Base
end end
def move_dir def move_dir
# Ensure old directory exists before moving it
gitlab_shell.add_namespace(path_was)
if gitlab_shell.mv_namespace(path_was, path) if gitlab_shell.mv_namespace(path_was, path)
# If repositories moved successfully we need to # If repositories moved successfully we need to
# send update instructions to users. # send update instructions to users.
......
- page_title "Report abuse"
%h3.page-title Report abuse
%p Please use this form to report users who create spam issues or comments or who otherwise behave inappropriately.
%hr
= form_for @abuse_report, html: { class: 'form-horizontal'} do |f|
= f.hidden_field :user_id
- if @abuse_report.errors.any?
.alert.alert-danger
- @abuse_report.errors.full_messages.each do |msg|
%p= msg
.form-group
= f.label :user_id, class: 'control-label'
.col-sm-10
- name = "#{@abuse_report.user.name} (@#{@abuse_report.user.username})"
= text_field_tag :user_name, name, class: "form-control", readonly: true
.form-group
= f.label :message, class: 'control-label'
.col-sm-10
= f.text_area :message, class: "form-control", rows: 2, required: true
.help-block
Explain the problem with this user. If appropriate, provide a link to the relevant issue or comment.
.form-actions
= f.submit "Send report", class: "btn btn-create"
- reporter = abuse_report.reporter
- user = abuse_report.user
%tr
%td
- if reporter
= link_to reporter.name, [:admin, reporter]
- else
(removed)
%td
= abuse_report.created_at.to_s(:short)
%td
= abuse_report.message
%td
- if user
= link_to user.name, [:admin, 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"
%td
= link_to 'Remove report', [:admin, abuse_report], method: :delete, class: "btn btn-xs btn-close"
- page_title "Abuse Reports"
%h3.page-title Abuse Reports
%hr
- if @abuse_reports.present?
%table.table
%thead
%tr
%th Reported by
%th Reported at
%th Message
%th User
%th
%th
= render @abuse_reports
= paginate @abuse_reports
- else
%h4 There are no abuse reports
...@@ -9,8 +9,8 @@ ...@@ -9,8 +9,8 @@
.project-info .project-info
- if project.description.present? - if project.description.present?
%p.project-description.str-truncated .project-description.str-truncated
= project.description = markdown(project.description, pipeline: :description)
.repo-info .repo-info
- unless project.empty_repo? - unless project.empty_repo?
......
...@@ -57,6 +57,13 @@ ...@@ -57,6 +57,13 @@
%span %span
Service Templates Service Templates
= nav_link(controller: :abuse_reports) do
= link_to admin_abuse_reports_path, title: "Abuse reports" do
= icon('exclamation-circle fw')
%span
Abuse Reports
%span.count= AbuseReport.count(:all)
= nav_link(controller: :application_settings, html_options: { class: 'separate-item'}) do = nav_link(controller: :application_settings, html_options: { class: 'separate-item'}) do
= link_to admin_application_settings_path, title: 'Settings', data: {placement: 'right'} do = link_to admin_application_settings_path, title: 'Settings', data: {placement: 'right'} do
= icon('cogs fw') = icon('cogs fw')
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
.project-identicon-holder .project-identicon-holder
= project_icon(@project, alt: '', class: 'project-avatar avatar s90') = project_icon(@project, alt: '', class: 'project-avatar avatar s90')
.project-home-desc.lead .project-home-desc.lead
%h1= @project.name
- if @project.description.present? - if @project.description.present?
= markdown(@project.description, pipeline: :description) = markdown(@project.description, pipeline: :description)
......
- if @merge_request.can_be_merged_by?(current_user) - if @merge_request.can_be_merged_by?(current_user)
%h4 %h4
This merge request contains merge conflicts that must be resolved. This merge request contains merge conflicts that must be resolved.
You can try it manually on the %p
You can merge it manually using the
%strong %strong
= link_to "command line", "#modal_merge_info", class: "how_to_merge_link vlink", title: "How To Merge", "data-toggle" => "modal" = link_to "command line", "#modal_merge_info", class: "how_to_merge_link vlink", title: "How To Merge", "data-toggle" => "modal"
- else - else
......
...@@ -12,18 +12,19 @@ ...@@ -12,18 +12,19 @@
.diff-content .diff-content
%table %table
- note.truncated_diff_lines.each do |line| - note.truncated_diff_lines.each do |line|
- type = line.type
- line_code = generate_line_code(note.file_path, line) - line_code = generate_line_code(note.file_path, line)
%tr.line_holder{ id: line_code } %tr.line_holder{ id: line_code, class: "#{type}" }
- if line.type == "match" - if type == "match"
%td.old_line= "..." %td.old_line= "..."
%td.new_line= "..." %td.new_line= "..."
%td.line_content.matched= line.text %td.line_content.matched= line.text
- else - else
%td.old_line{class: line.type == "new" ? "new" : "old"} %td.old_line
= raw(line.type == "new" ? "&nbsp;" : line.old_pos) = raw(type == "new" ? "&nbsp;" : line.old_pos)
%td.new_line{class: line.type == "new" ? "new" : "old"} %td.new_line
= raw(line.type == "old" ? "&nbsp;" : line.new_pos) = raw(type == "old" ? "&nbsp;" : line.new_pos)
%td.line_content{class: "noteable_line #{line.type} #{line_code}", "line_code" => line_code}= raw diff_line_content(line.text) %td.line_content{class: "noteable_line #{type} #{line_code}", "line_code" => line_code}= raw diff_line_content(line.text)
- if line_code == note.line_code - if line_code == note.line_code
= render "projects/notes/diff_notes_with_reply", notes: discussion_notes = render "projects/notes/diff_notes_with_reply", notes: discussion_notes
...@@ -18,6 +18,16 @@ ...@@ -18,6 +18,16 @@
= link_to profile_path, class: 'btn btn-sm' do = link_to profile_path, class: 'btn btn-sm' do
%i.fa.fa-pencil-square-o %i.fa.fa-pencil-square-o
Edit Profile settings Edit Profile settings
- elsif current_user
.pull-right
%span.dropdown
%a.light.dropdown-toggle.btn.btn-sm{href: '#', "data-toggle" => "dropdown"}
= icon('exclamation-circle')
%ul.dropdown-menu.dropdown-menu-right
%li
= link_to new_abuse_report_path(user_id: @user.id) do
Report abuse
.username .username
@#{@user.username} @#{@user.username}
.description .description
......
...@@ -65,6 +65,9 @@ Gitlab::Application.routes.draw do ...@@ -65,6 +65,9 @@ Gitlab::Application.routes.draw do
end end
end end
# Spam reports
resources :abuse_reports, only: [:new, :create]
# #
# Import # Import
# #
...@@ -165,6 +168,7 @@ Gitlab::Application.routes.draw do ...@@ -165,6 +168,7 @@ Gitlab::Application.routes.draw do
end end
end end
resources :abuse_reports, only: [:index, :destroy]
resources :applications resources :applications
resources :groups, constraints: { id: /[^\/]+/ } do resources :groups, constraints: { id: /[^\/]+/ } do
......
class CreateAbuseReports < ActiveRecord::Migration
def change
create_table :abuse_reports do |t|
t.integer :reporter_id
t.integer :user_id
t.text :message
t.timestamps
end
end
end
...@@ -11,11 +11,19 @@ ...@@ -11,11 +11,19 @@
# #
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20150730122406) do ActiveRecord::Schema.define(version: 20150806104937) do
# These are extensions that must be enabled in order to support this database # These are extensions that must be enabled in order to support this database
enable_extension "plpgsql" enable_extension "plpgsql"
create_table "abuse_reports", force: true do |t|
t.integer "reporter_id"
t.integer "user_id"
t.text "message"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "application_settings", force: true do |t| create_table "application_settings", force: true do |t|
t.integer "default_projects_limit" t.integer "default_projects_limit"
t.boolean "signup_enabled" t.boolean "signup_enabled"
......
Feature: Abuse reports
Background:
Given I sign in as a user
And user "Mike" exists
Scenario: Report abuse
Given I visit "Mike" user page
And I click "Report abuse" button
When I fill and submit abuse form
Then I should see success message
Feature: Admin Abuse reports
Background:
Given I sign in as an admin
And abuse reports exist
Scenario: Browse abuse reports
When I visit abuse reports page
Then I should see list of abuse reports
class Spinach::Features::AbuseReports < Spinach::FeatureSteps
include SharedAuthentication
step 'I visit "Mike" user page' do
visit user_path(user_mike)
end
step 'I click "Report abuse" button' do
click_link 'Report abuse'
end
step 'I fill and submit abuse form' do
fill_in 'abuse_report_message', with: 'This user send spam'
click_button 'Send report'
end
step 'I should see success message' do
page.should have_content 'Thank you for your report'
end
step 'user "Mike" exists' do
user_mike
end
def user_mike
@user_mike ||= create(:user, name: 'Mike')
end
end
class Spinach::Features::AdminAbuseReports < Spinach::FeatureSteps
include SharedAuthentication
include SharedPaths
include SharedAdmin
step 'I should see list of abuse reports' do
page.should have_content("Abuse Reports")
page.should have_content AbuseReport.first.message
page.should have_link("Remove user")
end
step 'abuse reports exist' do
create(:abuse_report)
end
end
...@@ -137,10 +137,11 @@ class Spinach::Features::ProjectForkedMergeRequests < Spinach::FeatureSteps ...@@ -137,10 +137,11 @@ class Spinach::Features::ProjectForkedMergeRequests < Spinach::FeatureSteps
end end
step 'I should see the users from the target project ID' do step 'I should see the users from the target project ID' do
expect(page).to have_selector('.user-result', visible: true, count: 2) expect(page).to have_selector('.user-result', visible: true, count: 3)
users = page.all('.user-name') users = page.all('.user-name')
expect(users[0].text).to eq 'Unassigned' expect(users[0].text).to eq 'Unassigned'
expect(users[1].text).to eq @project.users.first.name expect(users[1].text).to eq current_user.name
expect(users[2].text).to eq @project.users.first.name
end end
# Verify a link is generated against the correct project # Verify a link is generated against the correct project
......
...@@ -139,6 +139,10 @@ module SharedPaths ...@@ -139,6 +139,10 @@ module SharedPaths
visit admin_root_path visit admin_root_path
end end
step 'I visit abuse reports page' do
visit admin_abuse_reports_path
end
step 'I visit admin projects page' do step 'I visit admin projects page' do
visit admin_namespaces_projects_path visit admin_namespaces_projects_path
end end
......
...@@ -4,6 +4,7 @@ describe AutocompleteController do ...@@ -4,6 +4,7 @@ describe AutocompleteController do
let!(:project) { create(:project) } let!(:project) { create(:project) }
let!(:user) { create(:user) } let!(:user) { create(:user) }
let!(:user2) { create(:user) } let!(:user2) { create(:user) }
let!(:non_member) { create(:user) }
context 'project members' do context 'project members' do
before do before do
...@@ -61,6 +62,27 @@ describe AutocompleteController do ...@@ -61,6 +62,27 @@ describe AutocompleteController do
end end
end end
context 'non-member login for public project' do
let!(:project) { create(:project, :public) }
before do
sign_in(non_member)
project.team << [user, :master]
end
let(:body) { JSON.parse(response.body) }
describe 'GET #users with project ID' do
before do
get(:users, project_id: project.id)
end
it { expect(body).to be_kind_of(Array) }
it { expect(body.size).to eq 2 }
it { expect(body.map { |u| u['username'] }).to match_array([user.username, non_member.username]) }
end
end
context 'all users' do context 'all users' do
before do before do
sign_in(user) sign_in(user)
......
# Read about factories at https://github.com/thoughtbot/factory_girl
FactoryGirl.define do
factory :abuse_report do
reporter factory: :user
user
message 'User sends spam'
end
end
...@@ -22,9 +22,9 @@ feature 'Project', feature: true do ...@@ -22,9 +22,9 @@ feature 'Project', feature: true do
end end
it 'sanitizes unwanted tags' do it 'sanitizes unwanted tags' do
project.update_attribute(:description, '# Project Description') project.update_attribute(:description, "```\ncode\n```")
visit path visit path
expect(page).not_to have_css('.project-home-desc h1') expect(page).not_to have_css('.project-home-desc code')
end end
it 'permits `rel` attribute on links' do it 'permits `rel` attribute on links' do
......
require 'rails_helper'
RSpec.describe AbuseReport, type: :model do
subject { create(:abuse_report) }
it { expect(subject).to be_valid }
end
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