Merge branch 'master' into comment-updated-by
This commit is contained in:
commit
ad55f0d6f9
|
@ -1,8 +1,10 @@
|
|||
Please view this file on the master branch, on stable branches it's out of date.
|
||||
|
||||
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 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 network graph when branch name has single quotes (Stan Hu)
|
||||
- Add "Confirm user" button in user admin page (Stan Hu)
|
||||
|
@ -39,6 +41,10 @@ v 7.14.0 (unreleased)
|
|||
- Remove satellites
|
||||
- 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
|
||||
- Fix randomly failed spec
|
||||
- Create project services on Project creation
|
||||
|
|
|
@ -1 +1 @@
|
|||
2.6.3
|
||||
2.6.4
|
||||
|
|
|
@ -48,6 +48,10 @@
|
|||
display: block;
|
||||
}
|
||||
|
||||
.project-home-desc {
|
||||
font-size: 21px;
|
||||
}
|
||||
|
||||
.project-repo-buttons,
|
||||
.git-clone-holder {
|
||||
display: none;
|
||||
|
|
|
@ -30,7 +30,13 @@
|
|||
}
|
||||
}
|
||||
|
||||
.lead {
|
||||
.project-home-desc {
|
||||
h1 {
|
||||
margin: 0;
|
||||
margin-bottom: 10px;
|
||||
font-size: 26px;
|
||||
}
|
||||
|
||||
p {
|
||||
display: inline;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
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
|
|
@ -0,0 +1,11 @@
|
|||
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
|
|||
@users = @users.search(params[:search]) if params[:search].present?
|
||||
@users = @users.active
|
||||
@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]
|
||||
end
|
||||
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
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
|
|||
end
|
||||
|
||||
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 repositories moved successfully we need to
|
||||
# send update instructions to users.
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
- 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"
|
|
@ -0,0 +1,23 @@
|
|||
- 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"
|
|
@ -0,0 +1,17 @@
|
|||
- 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 @@
|
|||
|
||||
.project-info
|
||||
- if project.description.present?
|
||||
%p.project-description.str-truncated
|
||||
= project.description
|
||||
.project-description.str-truncated
|
||||
= markdown(project.description, pipeline: :description)
|
||||
|
||||
.repo-info
|
||||
- unless project.empty_repo?
|
||||
|
|
|
@ -57,6 +57,13 @@
|
|||
%span
|
||||
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
|
||||
= link_to admin_application_settings_path, title: 'Settings', data: {placement: 'right'} do
|
||||
= icon('cogs fw')
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
.project-identicon-holder
|
||||
= project_icon(@project, alt: '', class: 'project-avatar avatar s90')
|
||||
.project-home-desc.lead
|
||||
%h1= @project.name
|
||||
- if @project.description.present?
|
||||
= markdown(@project.description, pipeline: :description)
|
||||
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
- if @merge_request.can_be_merged_by?(current_user)
|
||||
%h4
|
||||
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
|
||||
= link_to "command line", "#modal_merge_info", class: "how_to_merge_link vlink", title: "How To Merge", "data-toggle" => "modal"
|
||||
- else
|
||||
|
|
|
@ -12,18 +12,19 @@
|
|||
.diff-content
|
||||
%table
|
||||
- note.truncated_diff_lines.each do |line|
|
||||
- type = line.type
|
||||
- line_code = generate_line_code(note.file_path, line)
|
||||
%tr.line_holder{ id: line_code }
|
||||
- if line.type == "match"
|
||||
%tr.line_holder{ id: line_code, class: "#{type}" }
|
||||
- if type == "match"
|
||||
%td.old_line= "..."
|
||||
%td.new_line= "..."
|
||||
%td.line_content.matched= line.text
|
||||
- else
|
||||
%td.old_line{class: line.type == "new" ? "new" : "old"}
|
||||
= raw(line.type == "new" ? " " : line.old_pos)
|
||||
%td.new_line{class: line.type == "new" ? "new" : "old"}
|
||||
= raw(line.type == "old" ? " " : line.new_pos)
|
||||
%td.line_content{class: "noteable_line #{line.type} #{line_code}", "line_code" => line_code}= raw diff_line_content(line.text)
|
||||
%td.old_line
|
||||
= raw(type == "new" ? " " : line.old_pos)
|
||||
%td.new_line
|
||||
= raw(type == "old" ? " " : line.new_pos)
|
||||
%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
|
||||
= render "projects/notes/diff_notes_with_reply", notes: discussion_notes
|
||||
|
|
|
@ -18,6 +18,16 @@
|
|||
= link_to profile_path, class: 'btn btn-sm' do
|
||||
%i.fa.fa-pencil-square-o
|
||||
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
|
||||
@#{@user.username}
|
||||
.description
|
||||
|
|
|
@ -65,6 +65,9 @@ Gitlab::Application.routes.draw do
|
|||
end
|
||||
end
|
||||
|
||||
# Spam reports
|
||||
resources :abuse_reports, only: [:new, :create]
|
||||
|
||||
#
|
||||
# Import
|
||||
#
|
||||
|
@ -165,6 +168,7 @@ Gitlab::Application.routes.draw do
|
|||
end
|
||||
end
|
||||
|
||||
resources :abuse_reports, only: [:index, :destroy]
|
||||
resources :applications
|
||||
|
||||
resources :groups, constraints: { id: /[^\/]+/ } do
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
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
|
10
db/schema.rb
10
db/schema.rb
|
@ -11,11 +11,19 @@
|
|||
#
|
||||
# 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
|
||||
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|
|
||||
t.integer "default_projects_limit"
|
||||
t.boolean "signup_enabled"
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
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
|
|
@ -0,0 +1,8 @@
|
|||
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
|
|
@ -0,0 +1,28 @@
|
|||
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
|
|
@ -0,0 +1,15 @@
|
|||
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
|
|||
end
|
||||
|
||||
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')
|
||||
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
|
||||
|
||||
# Verify a link is generated against the correct project
|
||||
|
|
|
@ -139,6 +139,10 @@ module SharedPaths
|
|||
visit admin_root_path
|
||||
end
|
||||
|
||||
step 'I visit abuse reports page' do
|
||||
visit admin_abuse_reports_path
|
||||
end
|
||||
|
||||
step 'I visit admin projects page' do
|
||||
visit admin_namespaces_projects_path
|
||||
end
|
||||
|
|
|
@ -4,6 +4,7 @@ describe AutocompleteController do
|
|||
let!(:project) { create(:project) }
|
||||
let!(:user) { create(:user) }
|
||||
let!(:user2) { create(:user) }
|
||||
let!(:non_member) { create(:user) }
|
||||
|
||||
context 'project members' do
|
||||
before do
|
||||
|
@ -61,6 +62,27 @@ describe AutocompleteController do
|
|||
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
|
||||
before do
|
||||
sign_in(user)
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
# 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
|
|||
end
|
||||
|
||||
it 'sanitizes unwanted tags' do
|
||||
project.update_attribute(:description, '# Project Description')
|
||||
project.update_attribute(:description, "```\ncode\n```")
|
||||
visit path
|
||||
expect(page).not_to have_css('.project-home-desc h1')
|
||||
expect(page).not_to have_css('.project-home-desc code')
|
||||
end
|
||||
|
||||
it 'permits `rel` attribute on links' do
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
require 'rails_helper'
|
||||
|
||||
RSpec.describe AbuseReport, type: :model do
|
||||
subject { create(:abuse_report) }
|
||||
|
||||
it { expect(subject).to be_valid }
|
||||
end
|
Loading…
Reference in New Issue