1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
|
# frozen_string_literal: true
class AbuseReport < ApplicationRecord
include CacheMarkdownField
include Sortable
include Gitlab::FileTypeDetection
include WithUploads
MAX_CHAR_LIMIT_URL = 512
MAX_FILE_SIZE = 1.megabyte
cache_markdown_field :message, pipeline: :single_line
belongs_to :reporter, class_name: 'User'
belongs_to :user
validates :reporter, presence: true
validates :user, presence: true
validates :message, presence: true
validates :category, presence: true
validates :user_id,
uniqueness: {
scope: [:reporter_id, :category],
message: ->(object, data) do
_('You have already reported this user')
end
}
validates :reported_from_url,
allow_blank: true,
length: { maximum: MAX_CHAR_LIMIT_URL },
addressable_url: {
dns_rebind_protection: true,
blocked_message: 'is an invalid URL. You can try reporting the abuse again, ' \
'or contact a GitLab administrator for help.'
}
validates :links_to_spam,
allow_blank: true,
length: {
maximum: 20,
message: N_("exceeds the limit of %{count} links")
}
before_validation :filter_empty_strings_from_links_to_spam
validate :links_to_spam_contains_valid_urls
mount_uploader :screenshot, AttachmentUploader
validates :screenshot, file_size: { maximum: MAX_FILE_SIZE }
validate :validate_screenshot_is_image
scope :by_user_id, ->(id) { where(user_id: id) }
scope :by_reporter_id, ->(id) { where(reporter_id: id) }
scope :by_category, ->(category) { where(category: category) }
scope :with_users, -> { includes(:reporter, :user) }
enum category: {
spam: 1,
offensive: 2,
phishing: 3,
crypto: 4,
credentials: 5,
copyright: 6,
malware: 7,
other: 8
}
enum status: {
open: 1,
closed: 2
}
# For CacheMarkdownField
alias_method :author, :reporter
HUMANIZED_ATTRIBUTES = {
reported_from_url: "Reported from"
}.freeze
def self.human_attribute_name(attr, options = {})
HUMANIZED_ATTRIBUTES[attr.to_sym] || super
end
def remove_user(deleted_by:)
user.delete_async(deleted_by: deleted_by, params: { hard_delete: true })
end
def notify
return unless persisted?
AbuseReportMailer.notify(id).deliver_later
end
def screenshot_path
return unless screenshot
return screenshot.url unless screenshot.upload
asset_host = ActionController::Base.asset_host || Gitlab.config.gitlab.base_url
local_path = Gitlab::Routing.url_helpers.abuse_report_upload_path(
filename: screenshot.filename,
id: screenshot.upload.model_id,
model: 'abuse_report',
mounted_as: 'screenshot')
Gitlab::Utils.append_path(asset_host, local_path)
end
private
def filter_empty_strings_from_links_to_spam
return if links_to_spam.blank?
links_to_spam.reject!(&:empty?)
end
def links_to_spam_contains_valid_urls
return if links_to_spam.blank?
links_to_spam.each do |link|
Gitlab::UrlBlocker.validate!(
link,
schemes: %w[http https],
allow_localhost: true,
dns_rebind_protection: true
)
next unless link.length > MAX_CHAR_LIMIT_URL
errors.add(
:links_to_spam,
format(_('contains URLs that exceed the %{limit} character limit'), limit: MAX_CHAR_LIMIT_URL)
)
end
rescue ::Gitlab::UrlBlocker::BlockedUrlError
errors.add(:links_to_spam, _('only supports valid HTTP(S) URLs'))
end
def filename
screenshot&.filename
end
def valid_image_extensions
Gitlab::FileTypeDetection::SAFE_IMAGE_EXT
end
def validate_screenshot_is_image
return if screenshot.blank?
return if image?
errors.add(
:screenshot,
format(
_('must match one of the following file types: %{extension_list}'),
extension_list: valid_image_extensions.to_sentence(last_word_connector: ' or '))
)
end
end
|