Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Jérome Perrin
gitlab-ce
Commits
2ace39f2
Commit
2ace39f2
authored
Feb 14, 2017
by
Oswaldo Ferreira
Committed by
Oswaldo Ferreira
Feb 21, 2017
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Spam check and reCAPTCHA improvements
parent
88152949
Changes
35
Hide whitespace changes
Inline
Side-by-side
Showing
35 changed files
with
935 additions
and
247 deletions
+935
-247
app/controllers/concerns/spammable_actions.rb
app/controllers/concerns/spammable_actions.rb
+24
-6
app/controllers/projects/issues_controller.rb
app/controllers/projects/issues_controller.rb
+9
-25
app/controllers/projects/snippets_controller.rb
app/controllers/projects/snippets_controller.rb
+8
-13
app/controllers/snippets_controller.rb
app/controllers/snippets_controller.rb
+8
-5
app/models/concerns/spammable.rb
app/models/concerns/spammable.rb
+1
-1
app/models/project_snippet.rb
app/models/project_snippet.rb
+0
-4
app/services/create_snippet_service.rb
app/services/create_snippet_service.rb
+6
-4
app/services/issuable_base_service.rb
app/services/issuable_base_service.rb
+18
-14
app/services/issues/create_service.rb
app/services/issues/create_service.rb
+5
-16
app/services/issues/update_service.rb
app/services/issues/update_service.rb
+8
-0
app/services/spam_check_service.rb
app/services/spam_check_service.rb
+24
-0
app/services/spam_service.rb
app/services/spam_service.rb
+22
-9
app/services/update_snippet_service.rb
app/services/update_snippet_service.rb
+8
-2
app/views/layouts/_recaptcha_verification.html.haml
app/views/layouts/_recaptcha_verification.html.haml
+23
-0
app/views/projects/issues/verify.html.haml
app/views/projects/issues/verify.html.haml
+3
-19
app/views/projects/snippets/verify.html.haml
app/views/projects/snippets/verify.html.haml
+4
-0
app/views/snippets/verify.html.haml
app/views/snippets/verify.html.haml
+4
-0
changelogs/unreleased/28093-snippet-and-issue-spam-check-on-edit.yml
...unreleased/28093-snippet-and-issue-spam-check-on-edit.yml
+4
-0
lib/api/helpers.rb
lib/api/helpers.rb
+4
-0
lib/api/issues.rb
lib/api/issues.rb
+5
-1
lib/api/project_snippets.rb
lib/api/project_snippets.rb
+7
-1
lib/api/snippets.rb
lib/api/snippets.rb
+6
-1
lib/api/v3/issues.rb
lib/api/v3/issues.rb
+6
-4
lib/api/v3/project_snippets.rb
lib/api/v3/project_snippets.rb
+7
-1
spec/controllers/projects/issues_controller_spec.rb
spec/controllers/projects/issues_controller_spec.rb
+109
-2
spec/controllers/projects/snippets_controller_spec.rb
spec/controllers/projects/snippets_controller_spec.rb
+165
-21
spec/controllers/snippets_controller_spec.rb
spec/controllers/snippets_controller_spec.rb
+156
-3
spec/models/concerns/spammable_spec.rb
spec/models/concerns/spammable_spec.rb
+1
-0
spec/requests/api/issues_spec.rb
spec/requests/api/issues_spec.rb
+27
-0
spec/requests/api/project_snippets_spec.rb
spec/requests/api/project_snippets_spec.rb
+66
-26
spec/requests/api/snippets_spec.rb
spec/requests/api/snippets_spec.rb
+61
-5
spec/requests/api/v3/issues_spec.rb
spec/requests/api/v3/issues_spec.rb
+27
-0
spec/requests/api/v3/project_snippets_spec.rb
spec/requests/api/v3/project_snippets_spec.rb
+66
-26
spec/services/issues/create_service_spec.rb
spec/services/issues/create_service_spec.rb
+0
-10
spec/services/spam_service_spec.rb
spec/services/spam_service_spec.rb
+43
-28
No files found.
app/controllers/concerns/spammable_actions.rb
View file @
2ace39f2
...
@@ -17,13 +17,31 @@ module SpammableActions
...
@@ -17,13 +17,31 @@ module SpammableActions
private
private
def
recaptcha_params
def
recaptcha_check_with_fallback
(
&
fallback
)
return
{}
unless
params
[
:recaptcha_verification
]
&&
Gitlab
::
Recaptcha
.
load_configurations!
&&
verify_recaptcha
if
spammable
.
valid?
redirect_to
spammable
elsif
render_recaptcha?
if
params
[
:recaptcha_verification
]
flash
[
:alert
]
=
'There was an error with the reCAPTCHA. Please solve the reCAPTCHA again.'
end
render
:verify
else
fallback
.
call
end
end
def
spammable_params
default_params
=
{
request:
request
}
recaptcha_check
=
params
[
:recaptcha_verification
]
&&
Gitlab
::
Recaptcha
.
load_configurations!
&&
verify_recaptcha
return
default_params
unless
recaptcha_check
{
{
recaptcha_verified:
true
,
recaptcha_verified:
true
,
spam_log_id:
params
[
:spam_log_id
]
}.
merge
(
default_params
)
spam_log_id:
params
[
:spam_log_id
]
}
end
end
def
spammable
def
spammable
...
...
app/controllers/projects/issues_controller.rb
View file @
2ace39f2
...
@@ -94,15 +94,15 @@ class Projects::IssuesController < Projects::ApplicationController
...
@@ -94,15 +94,15 @@ class Projects::IssuesController < Projects::ApplicationController
end
end
def
create
def
create
extra_params
=
{
request:
request
,
create_params
=
issue_params
merge_request_for_resolving_discussions:
merge_request_for_resolving_discussions
}
.
merge
(
merge_request_for_resolving_discussions:
merge_request_for_resolving_discussions
)
extra_params
.
merge!
(
recaptcha
_params
)
.
merge
(
spammable
_params
)
@issue
=
Issues
::
CreateService
.
new
(
project
,
current_user
,
issue_params
.
merge
(
extra_params
)
).
execute
@issue
=
Issues
::
CreateService
.
new
(
project
,
current_user
,
create_params
).
execute
respond_to
do
|
format
|
respond_to
do
|
format
|
format
.
html
do
format
.
html
do
html_response_create
recaptcha_check_with_fallback
{
render
:new
}
end
end
format
.
js
do
format
.
js
do
@link
=
@issue
.
attachment
.
url
.
to_js
@link
=
@issue
.
attachment
.
url
.
to_js
...
@@ -111,7 +111,9 @@ class Projects::IssuesController < Projects::ApplicationController
...
@@ -111,7 +111,9 @@ class Projects::IssuesController < Projects::ApplicationController
end
end
def
update
def
update
@issue
=
Issues
::
UpdateService
.
new
(
project
,
current_user
,
issue_params
).
execute
(
issue
)
update_params
=
issue_params
.
merge
(
spammable_params
)
@issue
=
Issues
::
UpdateService
.
new
(
project
,
current_user
,
update_params
).
execute
(
issue
)
if
params
[
:move_to_project_id
].
to_i
>
0
if
params
[
:move_to_project_id
].
to_i
>
0
new_project
=
Project
.
find
(
params
[
:move_to_project_id
])
new_project
=
Project
.
find
(
params
[
:move_to_project_id
])
...
@@ -123,11 +125,7 @@ class Projects::IssuesController < Projects::ApplicationController
...
@@ -123,11 +125,7 @@ class Projects::IssuesController < Projects::ApplicationController
respond_to
do
|
format
|
respond_to
do
|
format
|
format
.
html
do
format
.
html
do
if
@issue
.
valid?
recaptcha_check_with_fallback
{
render
:edit
}
redirect_to
issue_path
(
@issue
)
else
render
:edit
end
end
end
format
.
json
do
format
.
json
do
...
@@ -179,20 +177,6 @@ class Projects::IssuesController < Projects::ApplicationController
...
@@ -179,20 +177,6 @@ class Projects::IssuesController < Projects::ApplicationController
protected
protected
def
html_response_create
if
@issue
.
valid?
redirect_to
issue_path
(
@issue
)
elsif
render_recaptcha?
if
params
[
:recaptcha_verification
]
flash
[
:alert
]
=
'There was an error with the reCAPTCHA. Please solve the reCAPTCHA again.'
end
render
:verify
else
render
:new
end
end
def
issue
def
issue
# The Sortable default scope causes performance issues when used with find_by
# The Sortable default scope causes performance issues when used with find_by
@noteable
=
@issue
||=
@project
.
issues
.
where
(
iid:
params
[
:id
]).
reorder
(
nil
).
take
||
redirect_old
@noteable
=
@issue
||=
@project
.
issues
.
where
(
iid:
params
[
:id
]).
reorder
(
nil
).
take
||
redirect_old
...
...
app/controllers/projects/snippets_controller.rb
View file @
2ace39f2
...
@@ -38,24 +38,19 @@ class Projects::SnippetsController < Projects::ApplicationController
...
@@ -38,24 +38,19 @@ class Projects::SnippetsController < Projects::ApplicationController
end
end
def
create
def
create
create_params
=
snippet_params
.
merge
(
request:
request
)
create_params
=
snippet_params
.
merge
(
spammable_params
)
@snippet
=
CreateSnippetService
.
new
(
@project
,
current_user
,
create_params
).
execute
@snippet
=
CreateSnippetService
.
new
(
@project
,
current_user
,
create_params
).
execute
if
@snippet
.
valid?
recaptcha_check_with_fallback
{
render
:new
}
respond_with
(
@snippet
,
location:
namespace_project_snippet_path
(
@project
.
namespace
,
@project
,
@snippet
))
else
render
:new
end
end
end
def
update
def
update
UpdateSnippetService
.
new
(
project
,
current_user
,
@snippet
,
update_params
=
snippet_params
.
merge
(
spammable_params
)
snippet_params
).
execute
respond_with
(
@snippet
,
UpdateSnippetService
.
new
(
project
,
current_user
,
@snippet
,
update_params
).
execute
location:
namespace_project_snippet_path
(
@project
.
namespace
,
@project
,
@snippet
))
recaptcha_check_with_fallback
{
render
:edit
}
end
end
def
show
def
show
...
...
app/controllers/snippets_controller.rb
View file @
2ace39f2
...
@@ -42,16 +42,19 @@ class SnippetsController < ApplicationController
...
@@ -42,16 +42,19 @@ class SnippetsController < ApplicationController
end
end
def
create
def
create
create_params
=
snippet_params
.
merge
(
request:
request
)
create_params
=
snippet_params
.
merge
(
spammable_params
)
@snippet
=
CreateSnippetService
.
new
(
nil
,
current_user
,
create_params
).
execute
@snippet
=
CreateSnippetService
.
new
(
nil
,
current_user
,
create_params
).
execute
re
spond_with
@snippet
.
becomes
(
Snippet
)
re
captcha_check_with_fallback
{
render
:new
}
end
end
def
update
def
update
UpdateSnippetService
.
new
(
nil
,
current_user
,
@snippet
,
update_params
=
snippet_params
.
merge
(
spammable_params
)
snippet_params
).
execute
respond_with
@snippet
.
becomes
(
Snippet
)
UpdateSnippetService
.
new
(
nil
,
current_user
,
@snippet
,
update_params
).
execute
recaptcha_check_with_fallback
{
render
:edit
}
end
end
def
show
def
show
...
...
app/models/concerns/spammable.rb
View file @
2ace39f2
...
@@ -13,7 +13,7 @@ module Spammable
...
@@ -13,7 +13,7 @@ module Spammable
attr_accessor
:spam
attr_accessor
:spam
attr_accessor
:spam_log
attr_accessor
:spam_log
after_validation
:check_for_spam
,
on:
:create
after_validation
:check_for_spam
,
on:
[
:create
,
:update
]
cattr_accessor
:spammable_attrs
,
instance_accessor:
false
do
cattr_accessor
:spammable_attrs
,
instance_accessor:
false
do
[]
[]
...
...
app/models/project_snippet.rb
View file @
2ace39f2
...
@@ -9,8 +9,4 @@ class ProjectSnippet < Snippet
...
@@ -9,8 +9,4 @@ class ProjectSnippet < Snippet
participant
:author
participant
:author
participant
:notes_with_associations
participant
:notes_with_associations
def
check_for_spam?
super
&&
project
.
public?
end
end
end
app/services/create_snippet_service.rb
View file @
2ace39f2
class
CreateSnippetService
<
BaseService
class
CreateSnippetService
<
BaseService
include
SpamCheckService
def
execute
def
execute
request
=
params
.
delete
(
:request
)
filter_spam_check_params
api
=
params
.
delete
(
:api
)
snippet
=
if
project
snippet
=
if
project
project
.
snippets
.
build
(
params
)
project
.
snippets
.
build
(
params
)
...
@@ -15,10 +16,11 @@ class CreateSnippetService < BaseService
...
@@ -15,10 +16,11 @@ class CreateSnippetService < BaseService
end
end
snippet
.
author
=
current_user
snippet
.
author
=
current_user
snippet
.
spam
=
SpamService
.
new
(
snippet
,
request
).
check
(
api
)
spam_check
(
snippet
,
current_user
)
if
snippet
.
save
if
snippet
.
save
UserAgentDetailService
.
new
(
snippet
,
request
).
create
UserAgentDetailService
.
new
(
snippet
,
@
request
).
create
end
end
snippet
snippet
...
...
app/services/issuable_base_service.rb
View file @
2ace39f2
...
@@ -191,14 +191,12 @@ class IssuableBaseService < BaseService
...
@@ -191,14 +191,12 @@ class IssuableBaseService < BaseService
# To be overridden by subclasses
# To be overridden by subclasses
end
end
def
after
_update
(
issuable
)
def
before
_update
(
issuable
)
# To be overridden by subclasses
# To be overridden by subclasses
end
end
def
update_issuable
(
issuable
,
attributes
)
def
after_update
(
issuable
)
issuable
.
with_transaction_returning_status
do
# To be overridden by subclasses
issuable
.
update
(
attributes
.
merge
(
updated_by:
current_user
))
end
end
end
def
update
(
issuable
)
def
update
(
issuable
)
...
@@ -212,16 +210,22 @@ class IssuableBaseService < BaseService
...
@@ -212,16 +210,22 @@ class IssuableBaseService < BaseService
label_ids
=
process_label_ids
(
params
,
existing_label_ids:
issuable
.
label_ids
)
label_ids
=
process_label_ids
(
params
,
existing_label_ids:
issuable
.
label_ids
)
params
[
:label_ids
]
=
label_ids
if
labels_changing?
(
issuable
.
label_ids
,
label_ids
)
params
[
:label_ids
]
=
label_ids
if
labels_changing?
(
issuable
.
label_ids
,
label_ids
)
if
params
.
present?
&&
update_issuable
(
issuable
,
params
)
if
params
.
present?
# We do not touch as it will affect a update on updated_at field
issuable
.
assign_attributes
(
params
.
merge
(
updated_by:
current_user
))
ActiveRecord
::
Base
.
no_touching
do
handle_common_system_notes
(
issuable
,
old_labels:
old_labels
)
before_update
(
issuable
)
end
handle_changes
(
issuable
,
old_labels:
old_labels
,
old_mentioned_users:
old_mentioned_users
)
if
issuable
.
with_transaction_returning_status
{
issuable
.
save
}
after_update
(
issuable
)
# We do not touch as it will affect a update on updated_at field
issuable
.
create_new_cross_references!
(
current_user
)
ActiveRecord
::
Base
.
no_touching
do
execute_hooks
(
issuable
,
'update'
)
handle_common_system_notes
(
issuable
,
old_labels:
old_labels
)
end
handle_changes
(
issuable
,
old_labels:
old_labels
,
old_mentioned_users:
old_mentioned_users
)
after_update
(
issuable
)
issuable
.
create_new_cross_references!
(
current_user
)
execute_hooks
(
issuable
,
'update'
)
end
end
end
issuable
issuable
...
...
app/services/issues/create_service.rb
View file @
2ace39f2
module
Issues
module
Issues
class
CreateService
<
Issues
::
BaseService
class
CreateService
<
Issues
::
BaseService
include
SpamCheckService
def
execute
def
execute
@request
=
params
.
delete
(
:request
)
filter_spam_check_params
@api
=
params
.
delete
(
:api
)
@recaptcha_verified
=
params
.
delete
(
:recaptcha_verified
)
@spam_log_id
=
params
.
delete
(
:spam_log_id
)
issue_attributes
=
params
.
merge
(
merge_request_for_resolving_discussions:
merge_request_for_resolving_discussions
)
issue_attributes
=
params
.
merge
(
merge_request_for_resolving_discussions:
merge_request_for_resolving_discussions
)
@issue
=
BuildService
.
new
(
project
,
current_user
,
issue_attributes
).
execute
@issue
=
BuildService
.
new
(
project
,
current_user
,
issue_attributes
).
execute
...
@@ -12,14 +11,8 @@ module Issues
...
@@ -12,14 +11,8 @@ module Issues
create
(
@issue
)
create
(
@issue
)
end
end
def
before_create
(
issuable
)
def
before_create
(
issue
)
if
@recaptcha_verified
spam_check
(
issue
,
current_user
)
spam_log
=
current_user
.
spam_logs
.
find_by
(
id:
@spam_log_id
,
title:
issuable
.
title
)
spam_log
&
.
update!
(
recaptcha_verified:
true
)
else
issuable
.
spam
=
spam_service
.
check
(
@api
)
issuable
.
spam_log
=
spam_service
.
spam_log
end
end
end
def
after_create
(
issuable
)
def
after_create
(
issuable
)
...
@@ -42,10 +35,6 @@ module Issues
...
@@ -42,10 +35,6 @@ module Issues
private
private
def
spam_service
@spam_service
||=
SpamService
.
new
(
@issue
,
@request
)
end
def
user_agent_detail_service
def
user_agent_detail_service
UserAgentDetailService
.
new
(
@issue
,
@request
)
UserAgentDetailService
.
new
(
@issue
,
@request
)
end
end
...
...
app/services/issues/update_service.rb
View file @
2ace39f2
module
Issues
module
Issues
class
UpdateService
<
Issues
::
BaseService
class
UpdateService
<
Issues
::
BaseService
include
SpamCheckService
def
execute
(
issue
)
def
execute
(
issue
)
filter_spam_check_params
update
(
issue
)
update
(
issue
)
end
end
def
before_update
(
issue
)
spam_check
(
issue
,
current_user
)
end
def
handle_changes
(
issue
,
old_labels:
[],
old_mentioned_users:
[])
def
handle_changes
(
issue
,
old_labels:
[],
old_mentioned_users:
[])
if
has_changes?
(
issue
,
old_labels:
old_labels
)
if
has_changes?
(
issue
,
old_labels:
old_labels
)
todo_service
.
mark_pending_todos_as_done
(
issue
,
current_user
)
todo_service
.
mark_pending_todos_as_done
(
issue
,
current_user
)
...
...
app/services/spam_check_service.rb
0 → 100644
View file @
2ace39f2
# SpamCheckService
#
# Provide helper methods for checking if a given spammable object has
# potential spam data.
#
# Dependencies:
# - params with :request
#
module
SpamCheckService
def
filter_spam_check_params
@request
=
params
.
delete
(
:request
)
@api
=
params
.
delete
(
:api
)
@recaptcha_verified
=
params
.
delete
(
:recaptcha_verified
)
@spam_log_id
=
params
.
delete
(
:spam_log_id
)
end
def
spam_check
(
spammable
,
user
)
spam_service
=
SpamService
.
new
(
spammable
,
@request
)
spam_service
.
when_recaptcha_verified
(
@recaptcha_verified
,
@api
)
do
user
.
spam_logs
.
find_by
(
id:
@spam_log_id
)
&
.
update!
(
recaptcha_verified:
true
)
end
end
end
app/services/spam_service.rb
View file @
2ace39f2
...
@@ -17,15 +17,6 @@ class SpamService
...
@@ -17,15 +17,6 @@ class SpamService
end
end
end
end
def
check
(
api
=
false
)
return
false
unless
request
&&
check_for_spam?
return
false
unless
akismet
.
is_spam?
create_spam_log
(
api
)
true
end
def
mark_as_spam!
def
mark_as_spam!
return
false
unless
spammable
.
submittable_as_spam?
return
false
unless
spammable
.
submittable_as_spam?
...
@@ -36,8 +27,30 @@ class SpamService
...
@@ -36,8 +27,30 @@ class SpamService
end
end
end
end
def
when_recaptcha_verified
(
recaptcha_verified
,
api
=
false
)
# In case it's a request which is already verified through recaptcha, yield
# block.
if
recaptcha_verified
yield
else
# Otherwise, it goes to Akismet and check if it's a spam. If that's the
# case, it assigns spammable record as "spam" and create a SpamLog record.
spammable
.
spam
=
check
(
api
)
spammable
.
spam_log
=
spam_log
end
end
private
private
def
check
(
api
)
return
false
unless
request
&&
check_for_spam?
return
false
unless
akismet
.
is_spam?
create_spam_log
(
api
)
true
end
def
akismet
def
akismet
@akismet
||=
AkismetService
.
new
(
@akismet
||=
AkismetService
.
new
(
spammable_owner
,
spammable_owner
,
...
...
app/services/update_snippet_service.rb
View file @
2ace39f2
class
UpdateSnippetService
<
BaseService
class
UpdateSnippetService
<
BaseService
include
SpamCheckService
attr_accessor
:snippet
attr_accessor
:snippet
def
initialize
(
project
,
user
,
snippet
,
params
)
def
initialize
(
project
,
user
,
snippet
,
params
)
...
@@ -9,7 +11,7 @@ class UpdateSnippetService < BaseService
...
@@ -9,7 +11,7 @@ class UpdateSnippetService < BaseService
def
execute
def
execute
# check that user is allowed to set specified visibility_level
# check that user is allowed to set specified visibility_level
new_visibility
=
params
[
:visibility_level
]
new_visibility
=
params
[
:visibility_level
]
if
new_visibility
&&
new_visibility
.
to_i
!=
snippet
.
visibility_level
if
new_visibility
&&
new_visibility
.
to_i
!=
snippet
.
visibility_level
unless
Gitlab
::
VisibilityLevel
.
allowed_for?
(
current_user
,
new_visibility
)
unless
Gitlab
::
VisibilityLevel
.
allowed_for?
(
current_user
,
new_visibility
)
deny_visibility_level
(
snippet
,
new_visibility
)
deny_visibility_level
(
snippet
,
new_visibility
)
...
@@ -17,6 +19,10 @@ class UpdateSnippetService < BaseService
...
@@ -17,6 +19,10 @@ class UpdateSnippetService < BaseService
end
end
end
end
snippet
.
update_attributes
(
params
)
filter_spam_check_params
snippet
.
assign_attributes
(
params
)
spam_check
(
snippet
,
current_user
)
snippet
.
save
end
end
end
end
app/views/layouts/_recaptcha_verification.html.haml
0 → 100644
View file @
2ace39f2
-
humanized_resource_name
=
spammable
.
class
.
model_name
.
human
.
downcase
-
resource_name
=
spammable
.
class
.
model_name
.
singular
%h3
.page-title
Anti-spam verification
%hr
%p
#{
"We detected potential spam in the #{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
}
=
form_for
form
do
|
f
|
.recaptcha
-
params
[
resource_name
].
each
do
|
field
,
value
|
=
hidden_field
(
resource_name
,
field
,
value:
value
)
=
hidden_field_tag
(
:spam_log_id
,
spammable
.
spam_log
.
id
)
=
hidden_field_tag
(
:recaptcha_verification
,
true
)
=
recaptcha_tags
-# Yields a block with given extra params.
=
yield
.row-content-block.footer-block
=
f
.
submit
"Submit
#{
humanized_resource_name
}
"
,
class:
'btn btn-create'
app/views/projects/issues/verify.html.haml
View file @
2ace39f2
-
page_title
"Anti-spam verification"
-
form
=
[
@project
.
namespace
.
becomes
(
Namespace
),
@project
,
@issue
]
%h3
.page-title
=
render
layout:
'layouts/recaptcha_verification'
,
locals:
{
spammable:
@issue
,
form:
form
}
do
Anti-spam verification
=
hidden_field_tag
(
:merge_request_for_resolving_discussions
,
params
[
:merge_request_for_resolving_discussions
])
%hr
%p
We detected potential spam in the issue description. Please verify that you are not a robot to submit the issue.
=
form_for
[
@project
.
namespace
.
becomes
(
Namespace
),
@project
,
@issue
]
do
|
f
|
.recaptcha
-
params
[
:issue
].
each
do
|
field
,
value
|
=
hidden_field
(
:issue
,
field
,
value:
value
)
=
hidden_field_tag
(
:merge_request_for_resolving_discussions
,
params
[
:merge_request_for_resolving_discussions
])
=
hidden_field_tag
(
:spam_log_id
,
@issue
.
spam_log
.
id
)
=
hidden_field_tag
(
:recaptcha_verification
,
true
)
=
recaptcha_tags
.row-content-block.footer-block
=
f
.
submit
"Submit
#{
@issue
.
class
.
model_name
.
human
.
downcase
}
"
,
class:
'btn btn-create'
app/views/projects/snippets/verify.html.haml
0 → 100644
View file @
2ace39f2
-
form
=
[
@project
.
namespace
.
becomes
(
Namespace
),
@project
,
@snippet
.
becomes
(
Snippet
)]
=
render
'layouts/recaptcha_verification'
,
spammable:
@snippet
,
form:
form
app/views/snippets/verify.html.haml
0 → 100644
View file @
2ace39f2
-
form
=
[
@snippet
.
becomes
(
Snippet
)]
=
render
'layouts/recaptcha_verification'
,
spammable:
@snippet
,
form:
form
changelogs/unreleased/28093-snippet-and-issue-spam-check-on-edit.yml
0 → 100644
View file @
2ace39f2
---
title
:
Spam check and reCAPTCHA improvements
merge_request
:
author
:
lib/api/helpers.rb
View file @
2ace39f2
...
@@ -215,6 +215,10 @@ module API
...
@@ -215,6 +215,10 @@ module API
end
end
end
end
def
render_spam_error!
render_api_error!
({
error:
'Spam detected'
},
400
)
end
def
render_api_error!
(
message
,
status
)
def
render_api_error!
(
message
,
status
)
error!
({
'message'
=>
message
},
status
,
header
)
error!
({
'message'
=>
message
},
status
,
header
)
end
end
...
...
lib/api/issues.rb
View file @
2ace39f2
...
@@ -169,9 +169,13 @@ module API
...
@@ -169,9 +169,13 @@ module API
params
.
delete
(
:updated_at
)
params
.
delete
(
:updated_at
)
end
end
update_params
=
declared_params
(
include_missing:
false
).
merge
(
request:
request
,
api:
true
)
issue
=
::
Issues
::
UpdateService
.
new
(
user_project
,
issue
=
::
Issues
::
UpdateService
.
new
(
user_project
,
current_user
,
current_user
,
declared_params
(
include_missing:
false
)).
execute
(
issue
)
update_params
).
execute
(
issue
)
render_spam_error!
if
issue
.
spam?
if
issue
.
valid?
if
issue
.
valid?
present
issue
,
with:
Entities
::
Issue
,
current_user:
current_user
,
project:
user_project
present
issue
,
with:
Entities
::
Issue
,
current_user:
current_user
,
project:
user_project
...
...
lib/api/project_snippets.rb
View file @
2ace39f2
...
@@ -63,6 +63,8 @@ module API
...
@@ -63,6 +63,8 @@ module API
snippet
=
CreateSnippetService
.
new
(
user_project
,
current_user
,
snippet_params
).
execute
snippet
=
CreateSnippetService
.
new
(
user_project
,
current_user
,
snippet_params
).
execute
render_spam_error!
if
snippet
.
spam?
if
snippet
.
persisted?
if
snippet
.
persisted?
present
snippet
,
with:
Entities
::
ProjectSnippet
present
snippet
,
with:
Entities
::
ProjectSnippet
else
else
...
@@ -92,12 +94,16 @@ module API
...
@@ -92,12 +94,16 @@ module API
authorize!
:update_project_snippet
,
snippet
authorize!
:update_project_snippet
,
snippet
snippet_params
=
declared_params
(
include_missing:
false
)
snippet_params
=
declared_params
(
include_missing:
false
)
.
merge
(
request:
request
,
api:
true
)
snippet_params
[
:content
]
=
snippet_params
.
delete
(
:code
)
if
snippet_params
[
:code
].
present?
snippet_params
[
:content
]
=
snippet_params
.
delete
(
:code
)
if
snippet_params
[
:code
].
present?
UpdateSnippetService
.
new
(
user_project
,
current_user
,
snippet
,
UpdateSnippetService
.
new
(
user_project
,
current_user
,
snippet
,
snippet_params
).
execute
snippet_params
).
execute
if
snippet
.
persisted?
render_spam_error!
if
snippet
.
spam?
if
snippet
.
valid?
present
snippet
,
with:
Entities
::
ProjectSnippet
present
snippet
,
with:
Entities
::
ProjectSnippet
else
else
render_validation_error!
(
snippet
)
render_validation_error!
(
snippet
)
...
...
lib/api/snippets.rb
View file @
2ace39f2
...
@@ -67,6 +67,8 @@ module API
...
@@ -67,6 +67,8 @@ module API
attrs
=
declared_params
(
include_missing:
false
).
merge
(
request:
request
,
api:
true
)
attrs
=
declared_params
(
include_missing:
false
).
merge
(
request:
request
,
api:
true
)
snippet
=
CreateSnippetService
.
new
(
nil
,
current_user
,
attrs
).
execute
snippet
=
CreateSnippetService
.
new
(
nil
,
current_user
,
attrs
).
execute
render_spam_error!
if
snippet
.
spam?
if
snippet
.
persisted?
if
snippet
.
persisted?
present
snippet
,
with:
Entities
::
PersonalSnippet
present
snippet
,
with:
Entities
::
PersonalSnippet
else
else
...
@@ -93,9 +95,12 @@ module API
...
@@ -93,9 +95,12 @@ module API
return
not_found!
(
'Snippet'
)
unless
snippet
return
not_found!
(
'Snippet'
)
unless
snippet
authorize!
:update_personal_snippet
,
snippet
authorize!
:update_personal_snippet
,
snippet
attrs
=
declared_params
(
include_missing:
false
)
attrs
=
declared_params
(
include_missing:
false
)
.
merge
(
request:
request
,
api:
true
)
UpdateSnippetService
.
new
(
nil
,
current_user
,
snippet
,
attrs
).
execute
UpdateSnippetService
.
new
(
nil
,
current_user
,
snippet
,
attrs
).
execute
render_spam_error!
if
snippet
.
spam?
if
snippet
.
persisted?
if
snippet
.
persisted?
present
snippet
,
with:
Entities
::
PersonalSnippet
present
snippet
,
with:
Entities
::
PersonalSnippet
else
else
...
...
lib/api/v3/issues.rb
View file @
2ace39f2
...
@@ -149,9 +149,7 @@ module API
...
@@ -149,9 +149,7 @@ module API
issue
=
::
Issues
::
CreateService
.
new
(
user_project
,
issue
=
::
Issues
::
CreateService
.
new
(
user_project
,
current_user
,
current_user
,
issue_params
.
merge
(
request:
request
,
api:
true
)).
execute
issue_params
.
merge
(
request:
request
,
api:
true
)).
execute
if
issue
.
spam?
render_spam_error!
if
issue
.
spam?
render_api_error!
({
error:
'Spam detected'
},
400
)
end
if
issue
.
valid?
if
issue
.
valid?
present
issue
,
with:
::
API
::
Entities
::
Issue
,
current_user:
current_user
,
project:
user_project
present
issue
,
with:
::
API
::
Entities
::
Issue
,
current_user:
current_user
,
project:
user_project
...
@@ -182,9 +180,13 @@ module API
...
@@ -182,9 +180,13 @@ module API
params
.
delete
(
:updated_at
)
params
.
delete
(
:updated_at
)
end
end
update_params
=
declared_params
(
include_missing:
false
).
merge
(
request:
request
,
api:
true
)
issue
=
::
Issues
::
UpdateService
.
new
(
user_project
,
issue
=
::
Issues
::
UpdateService
.
new
(
user_project
,
current_user
,
current_user
,
declared_params
(
include_missing:
false
)).
execute
(
issue
)
update_params
).
execute
(
issue
)
render_spam_error!
if
issue
.
spam?
if
issue
.
valid?
if
issue
.
valid?
present
issue
,
with:
::
API
::
Entities
::
Issue
,
current_user:
current_user
,
project:
user_project
present
issue
,
with:
::
API
::
Entities
::
Issue
,
current_user:
current_user
,
project:
user_project
...
...
lib/api/v3/project_snippets.rb
View file @
2ace39f2
...
@@ -64,6 +64,8 @@ module API
...
@@ -64,6 +64,8 @@ module API
snippet
=
CreateSnippetService
.
new
(
user_project
,
current_user
,
snippet_params
).
execute
snippet
=
CreateSnippetService
.
new
(
user_project
,
current_user
,
snippet_params
).
execute
render_spam_error!
if
snippet
.
spam?
if
snippet
.
persisted?
if
snippet
.
persisted?
present
snippet
,
with:
::
API
::
V3
::
Entities
::
ProjectSnippet
present
snippet
,
with:
::
API
::
V3
::
Entities
::
ProjectSnippet
else
else
...
@@ -93,12 +95,16 @@ module API
...
@@ -93,12 +95,16 @@ module API
authorize!
:update_project_snippet
,
snippet
authorize!
:update_project_snippet
,
snippet
snippet_params
=
declared_params
(
include_missing:
false
)
snippet_params
=
declared_params
(
include_missing:
false
)
.
merge
(
request:
request
,
api:
true
)
snippet_params
[
:content
]
=
snippet_params
.
delete
(
:code
)
if
snippet_params
[
:code
].
present?
snippet_params
[
:content
]
=
snippet_params
.
delete
(
:code
)
if
snippet_params
[
:code
].
present?
UpdateSnippetService
.
new
(
user_project
,
current_user
,
snippet
,
UpdateSnippetService
.
new
(
user_project
,
current_user
,
snippet
,
snippet_params
).
execute
snippet_params
).
execute
if
snippet
.
persisted?
render_spam_error!
if
snippet
.
spam?
if
snippet
.
valid?
present
snippet
,
with:
::
API
::
V3
::
Entities
::
ProjectSnippet
present
snippet
,
with:
::
API
::
V3
::
Entities
::
ProjectSnippet
else
else
render_validation_error!
(
snippet
)
render_validation_error!
(
snippet
)
...
...
spec/controllers/projects/issues_controller_spec.rb
View file @
2ace39f2
...
@@ -152,6 +152,113 @@ describe Projects::IssuesController do
...
@@ -152,6 +152,113 @@ describe Projects::IssuesController do
end
end
end
end
context
'Akismet is enabled'
do
let
(
:project
)
{
create
(
:project_empty_repo
,
:public
)
}
before
do
stub_application_setting
(
recaptcha_enabled:
true
)
allow_any_instance_of
(
SpamService
).
to
receive
(
:check_for_spam?
).
and_return
(
true
)
end
context
'when an issue is not identified as spam'
do
before
do
allow_any_instance_of
(
described_class
).
to
receive
(
:verify_recaptcha
).
and_return
(
false
)
allow_any_instance_of
(
AkismetService
).
to
receive
(
:is_spam?
).
and_return
(
false
)
end
it
'normally updates the issue'
do
expect
{
update_issue
(
title:
'Foo'
)
}.
to
change
{
issue
.
reload
.
title
}.
to
(
'Foo'
)
end
end
context
'when an issue is identified as spam'
do
before
{
allow_any_instance_of
(
AkismetService
).
to
receive
(
:is_spam?
).
and_return
(
true
)
}
context
'when captcha is not verified'
do
def
update_spam_issue
update_issue
(
title:
'Spam Title'
,
description:
'Spam lives here'
)
end
before
{
allow_any_instance_of
(
described_class
).
to
receive
(
:verify_recaptcha
).
and_return
(
false
)
}
it
'rejects an issue recognized as a spam'
do
expect
{
update_spam_issue
}.
not_to
change
{
issue
.
reload
.
title
}
end
it
'rejects an issue recognized as a spam when recaptcha disabled'
do
stub_application_setting
(
recaptcha_enabled:
false
)
expect
{
update_spam_issue
}.
not_to
change
{
issue
.
reload
.
title
}
end
it
'creates a spam log'
do
update_spam_issue
spam_logs
=
SpamLog
.
all
expect
(
spam_logs
.
count
).
to
eq
(
1
)
expect
(
spam_logs
.
first
.
title
).
to
eq
(
'Spam Title'
)
expect
(
spam_logs
.
first
.
recaptcha_verified
).
to
be_falsey
end
it
'renders verify template'
do
update_spam_issue
expect
(
response
).
to
render_template
(
:verify
)
end
end
context
'when captcha is verified'
do
let
(
:spammy_title
)
{
'Whatever'
}
let!
(
:spam_logs
)
{
create_list
(
:spam_log
,
2
,
user:
user
,
title:
spammy_title
)
}
def
update_verified_issue
update_issue
({
title:
spammy_title
},
{
spam_log_id:
spam_logs
.
last
.
id
,
recaptcha_verification:
true
})
end
before
do
allow_any_instance_of
(
described_class
).
to
receive
(
:verify_recaptcha
)
.
and_return
(
true
)
end
it
'redirect to issue page'
do
update_verified_issue
expect
(
response
).
to
redirect_to
(
namespace_project_issue_path
(
project
.
namespace
,
project
,
issue
))
end
it
'accepts an issue after recaptcha is verified'
do
expect
{
update_verified_issue
}.
to
change
{
issue
.
reload
.
title
}.
to
(
spammy_title
)
end
it
'marks spam log as recaptcha_verified'
do
expect
{
update_verified_issue
}.
to
change
{
SpamLog
.
last
.
recaptcha_verified
}.
from
(
false
).
to
(
true
)
end
it
'does not mark spam log as recaptcha_verified when it does not belong to current_user'
do
spam_log
=
create
(
:spam_log
)
expect
{
update_issue
(
spam_log_id:
spam_log
.
id
,
recaptcha_verification:
true
)
}.
not_to
change
{
SpamLog
.
last
.
recaptcha_verified
}
end
end
end
end
def
update_issue
(
issue_params
=
{},
additional_params
=
{})
params
=
{
namespace_id:
project
.
namespace
.
to_param
,
project_id:
project
.
to_param
,
id:
issue
.
iid
,
issue:
issue_params
}.
merge
(
additional_params
)
put
:update
,
params
end
def
move_issue
def
move_issue
put
:update
,
put
:update
,
namespace_id:
project
.
namespace
.
to_param
,
namespace_id:
project
.
namespace
.
to_param
,
...
@@ -384,7 +491,7 @@ describe Projects::IssuesController do
...
@@ -384,7 +491,7 @@ describe Projects::IssuesController do
allow_any_instance_of
(
SpamService
).
to
receive
(
:check_for_spam?
).
and_return
(
true
)
allow_any_instance_of
(
SpamService
).
to
receive
(
:check_for_spam?
).
and_return
(
true
)
end
end
context
'when an issue is not identified as
a
spam'
do
context
'when an issue is not identified as spam'
do
before
do
before
do
allow_any_instance_of
(
described_class
).
to
receive
(
:verify_recaptcha
).
and_return
(
false
)
allow_any_instance_of
(
described_class
).
to
receive
(
:verify_recaptcha
).
and_return
(
false
)
allow_any_instance_of
(
AkismetService
).
to
receive
(
:is_spam?
).
and_return
(
false
)
allow_any_instance_of
(
AkismetService
).
to
receive
(
:is_spam?
).
and_return
(
false
)
...
@@ -395,7 +502,7 @@ describe Projects::IssuesController do
...
@@ -395,7 +502,7 @@ describe Projects::IssuesController do
end
end
end
end
context
'when an issue is identified as
a
spam'
do
context
'when an issue is identified as spam'
do
before
{
allow_any_instance_of
(
AkismetService
).
to
receive
(
:is_spam?
).
and_return
(
true
)
}
before
{
allow_any_instance_of
(
AkismetService
).
to
receive
(
:is_spam?
).
and_return
(
true
)
}
context
'when captcha is not verified'
do
context
'when captcha is not verified'
do
...
...
spec/controllers/projects/snippets_controller_spec.rb
View file @
2ace39f2
...
@@ -70,7 +70,7 @@ describe Projects::SnippetsController do
...
@@ -70,7 +70,7 @@ describe Projects::SnippetsController do
end
end
describe
'POST #create'
do
describe
'POST #create'
do
def
create_snippet
(
project
,
snippet_params
=
{})
def
create_snippet
(
project
,
snippet_params
=
{}
,
additional_params
=
{}
)
sign_in
(
user
)
sign_in
(
user
)
project
.
add_developer
(
user
)
project
.
add_developer
(
user
)
...
@@ -79,7 +79,7 @@ describe Projects::SnippetsController do
...
@@ -79,7 +79,7 @@ describe Projects::SnippetsController do
namespace_id:
project
.
namespace
.
to_param
,
namespace_id:
project
.
namespace
.
to_param
,
project_id:
project
.
to_param
,
project_id:
project
.
to_param
,
project_snippet:
{
title:
'Title'
,
content:
'Content'
}.
merge
(
snippet_params
)
project_snippet:
{
title:
'Title'
,
content:
'Content'
}.
merge
(
snippet_params
)
}
}
.
merge
(
additional_params
)
end
end
context
'when the snippet is spam'
do
context
'when the snippet is spam'
do
...
@@ -87,35 +87,179 @@ describe Projects::SnippetsController do
...
@@ -87,35 +87,179 @@ describe Projects::SnippetsController do
allow_any_instance_of
(
AkismetService
).
to
receive
(
:is_spam?
).
and_return
(
true
)
allow_any_instance_of
(
AkismetService
).
to
receive
(
:is_spam?
).
and_return
(
true
)
end
end
context
'when the project is private'
do
context
'when the snippet is private'
do
let
(
:private_project
)
{
create
(
:project_empty_repo
,
:private
)
}
it
'creates the snippet'
do
expect
{
create_snippet
(
project
,
visibility_level:
Snippet
::
PRIVATE
)
}.
to
change
{
Snippet
.
count
}.
by
(
1
)
end
end
context
'when the snippet is public'
do
it
'rejects the shippet'
do
expect
{
create_snippet
(
project
,
visibility_level:
Snippet
::
PUBLIC
)
}.
not_to
change
{
Snippet
.
count
}
expect
(
response
).
to
render_template
(
:new
)
end
it
'creates a spam log'
do
expect
{
create_snippet
(
project
,
visibility_level:
Snippet
::
PUBLIC
)
}.
to
change
{
SpamLog
.
count
}.
by
(
1
)
end
it
'renders :new with recaptcha disabled'
do
stub_application_setting
(
recaptcha_enabled:
false
)
create_snippet
(
project
,
visibility_level:
Snippet
::
PUBLIC
)
expect
(
response
).
to
render_template
(
:new
)
end
context
'when the snippet is public'
do
context
'recaptcha enabled'
do
it
'creates the snippet'
do
before
do
expect
{
create_snippet
(
private_project
,
visibility_level:
Snippet
::
PUBLIC
)
}.
stub_application_setting
(
recaptcha_enabled:
true
)
to
change
{
Snippet
.
count
}.
by
(
1
)
end
end
it
'renders :verify with recaptcha enabled'
do
create_snippet
(
project
,
visibility_level:
Snippet
::
PUBLIC
)
expect
(
response
).
to
render_template
(
:verify
)
end
it
'renders snippet page when recaptcha verified'
do
spammy_title
=
'Whatever'
spam_logs
=
create_list
(
:spam_log
,
2
,
user:
user
,
title:
spammy_title
)
create_snippet
(
project
,
{
visibility_level:
Snippet
::
PUBLIC
},
{
spam_log_id:
spam_logs
.
last
.
id
,
recaptcha_verification:
true
})
expect
(
response
).
to
redirect_to
(
Snippet
.
last
)
end
end
end
end
end
describe
'PUT #update'
do
let
(
:project
)
{
create
:project
,
:public
}
let
(
:snippet
)
{
create
:project_snippet
,
author:
user
,
project:
project
,
visibility_level:
visibility_level
}
def
update_snippet
(
snippet_params
=
{},
additional_params
=
{})
sign_in
(
user
)
project
.
add_developer
(
user
)
put
:update
,
{
namespace_id:
project
.
namespace
.
to_param
,
project_id:
project
.
to_param
,
id:
snippet
.
id
,
project_snippet:
{
title:
'Title'
,
content:
'Content'
}.
merge
(
snippet_params
)
}.
merge
(
additional_params
)
snippet
.
reload
end
context
'when the snippet is spam'
do
before
do
allow_any_instance_of
(
AkismetService
).
to
receive
(
:is_spam?
).
and_return
(
true
)
end
context
'when the snippet is private'
do
let
(
:visibility_level
)
{
Snippet
::
PRIVATE
}
it
'updates the snippet'
do
expect
{
update_snippet
(
title:
'Foo'
)
}.
to
change
{
snippet
.
reload
.
title
}.
to
(
'Foo'
)
end
end
end
end
context
'when the project is public'
do
context
'when the snippet is public'
do
context
'when the snippet is private'
do
let
(
:visibility_level
)
{
Snippet
::
PUBLIC
}
it
'creates the snippet'
do
expect
{
create_snippet
(
project
,
visibility_level:
Snippet
::
PRIVATE
)
}.
it
'rejects the shippet'
do
to
change
{
Snippet
.
count
}.
by
(
1
)
expect
{
update_snippet
(
title:
'Foo'
)
}.
not_to
change
{
snippet
.
reload
.
title
}
end
it
'creates a spam log'
do
expect
{
update_snippet
(
title:
'Foo'
)
}.
to
change
{
SpamLog
.
count
}.
by
(
1
)
end
it
'renders :edit with recaptcha disabled'
do
stub_application_setting
(
recaptcha_enabled:
false
)
update_snippet
(
title:
'Foo'
)
expect
(
response
).
to
render_template
(
:edit
)
end
context
'recaptcha enabled'
do
before
do
stub_application_setting
(
recaptcha_enabled:
true
)
end
it
'renders :verify with recaptcha enabled'
do
update_snippet
(
title:
'Foo'
)
expect
(
response
).
to
render_template
(
:verify
)
end
it
'renders snippet page when recaptcha verified'
do
spammy_title
=
'Whatever'
spam_logs
=
create_list
(
:spam_log
,
2
,
user:
user
,
title:
spammy_title
)
snippet
=
update_snippet
({
title:
spammy_title
},
{
spam_log_id:
spam_logs
.
last
.
id
,
recaptcha_verification:
true
})
expect
(
response
).
to
redirect_to
(
snippet
)
end
end
end
end
end
context
'when the private snippet is made public'
do
let
(
:visibility_level
)
{
Snippet
::
PRIVATE
}
it
'rejects the shippet'
do
expect
{
update_snippet
(
title:
'Foo'
,
visibility_level:
Snippet
::
PUBLIC
)
}.
not_to
change
{
snippet
.
reload
.
title
}
end
it
'creates a spam log'
do
expect
{
update_snippet
(
title:
'Foo'
,
visibility_level:
Snippet
::
PUBLIC
)
}.
to
change
{
SpamLog
.
count
}.
by
(
1
)
end
it
'renders :edit with recaptcha disabled'
do
stub_application_setting
(
recaptcha_enabled:
false
)
context
'when the snippet is public'
do
update_snippet
(
title:
'Foo'
,
visibility_level:
Snippet
::
PUBLIC
)
it
'rejects the shippet'
do
expect
{
create_snippet
(
project
,
visibility_level:
Snippet
::
PUBLIC
)
}.
expect
(
response
).
to
render_template
(
:edit
)
not_to
change
{
Snippet
.
count
}
end
expect
(
response
).
to
render_template
(
:new
)
context
'recaptcha enabled'
do
before
do
stub_application_setting
(
recaptcha_enabled:
true
)
end
it
'renders :verify with recaptcha enabled'
do
update_snippet
(
title:
'Foo'
,
visibility_level:
Snippet
::
PUBLIC
)
expect
(
response
).
to
render_template
(
:verify
)
end
end
it
'creates a spam log'
do
it
'renders snippet page when recaptcha verified'
do
expect
{
create_snippet
(
project
,
visibility_level:
Snippet
::
PUBLIC
)
}.
spammy_title
=
'Whatever'
to
change
{
SpamLog
.
count
}.
by
(
1
)
spam_logs
=
create_list
(
:spam_log
,
2
,
user:
user
,
title:
spammy_title
)
snippet
=
update_snippet
({
title:
spammy_title
,
visibility_level:
Snippet
::
PUBLIC
},
{
spam_log_id:
spam_logs
.
last
.
id
,
recaptcha_verification:
true
})
expect
(
response
).
to
redirect_to
(
snippet
)
end
end
end
end
end
end
...
...
spec/controllers/snippets_controller_spec.rb
View file @
2ace39f2
...
@@ -139,12 +139,14 @@ describe SnippetsController do
...
@@ -139,12 +139,14 @@ describe SnippetsController do
end
end
describe
'POST #create'
do
describe
'POST #create'
do
def
create_snippet
(
snippet_params
=
{})
def
create_snippet
(
snippet_params
=
{}
,
additional_params
=
{}
)
sign_in
(
user
)
sign_in
(
user
)
post
:create
,
{
post
:create
,
{
personal_snippet:
{
title:
'Title'
,
content:
'Content'
}.
merge
(
snippet_params
)
personal_snippet:
{
title:
'Title'
,
content:
'Content'
}.
merge
(
snippet_params
)
}
}.
merge
(
additional_params
)
Snippet
.
last
end
end
context
'when the snippet is spam'
do
context
'when the snippet is spam'
do
...
@@ -163,13 +165,164 @@ describe SnippetsController do
...
@@ -163,13 +165,164 @@ describe SnippetsController do
it
'rejects the shippet'
do
it
'rejects the shippet'
do
expect
{
create_snippet
(
visibility_level:
Snippet
::
PUBLIC
)
}.
expect
{
create_snippet
(
visibility_level:
Snippet
::
PUBLIC
)
}.
not_to
change
{
Snippet
.
count
}
not_to
change
{
Snippet
.
count
}
expect
(
response
).
to
render_template
(
:new
)
end
end
it
'creates a spam log'
do
it
'creates a spam log'
do
expect
{
create_snippet
(
visibility_level:
Snippet
::
PUBLIC
)
}.
expect
{
create_snippet
(
visibility_level:
Snippet
::
PUBLIC
)
}.
to
change
{
SpamLog
.
count
}.
by
(
1
)
to
change
{
SpamLog
.
count
}.
by
(
1
)
end
end
it
'renders :new with recaptcha disabled'
do
stub_application_setting
(
recaptcha_enabled:
false
)
create_snippet
(
visibility_level:
Snippet
::
PUBLIC
)
expect
(
response
).
to
render_template
(
:new
)
end
context
'recaptcha enabled'
do
before
do
stub_application_setting
(
recaptcha_enabled:
true
)
end
it
'renders :verify with recaptcha enabled'
do
create_snippet
(
visibility_level:
Snippet
::
PUBLIC
)
expect
(
response
).
to
render_template
(
:verify
)
end
it
'renders snippet page when recaptcha verified'
do
spammy_title
=
'Whatever'
spam_logs
=
create_list
(
:spam_log
,
2
,
user:
user
,
title:
spammy_title
)
snippet
=
create_snippet
({
title:
spammy_title
},
{
spam_log_id:
spam_logs
.
last
.
id
,
recaptcha_verification:
true
})
expect
(
response
).
to
redirect_to
(
snippet_path
(
snippet
))
end
end
end
end
end
describe
'PUT #update'
do
let
(
:project
)
{
create
:project
}
let
(
:snippet
)
{
create
:personal_snippet
,
author:
user
,
project:
project
,
visibility_level:
visibility_level
}
def
update_snippet
(
snippet_params
=
{},
additional_params
=
{})
sign_in
(
user
)
put
:update
,
{
id:
snippet
.
id
,
personal_snippet:
{
title:
'Title'
,
content:
'Content'
}.
merge
(
snippet_params
)
}.
merge
(
additional_params
)
snippet
.
reload
end
context
'when the snippet is spam'
do
before
do
allow_any_instance_of
(
AkismetService
).
to
receive
(
:is_spam?
).
and_return
(
true
)
end
context
'when the snippet is private'
do
let
(
:visibility_level
)
{
Snippet
::
PRIVATE
}
it
'updates the snippet'
do
expect
{
update_snippet
(
title:
'Foo'
)
}.
to
change
{
snippet
.
reload
.
title
}.
to
(
'Foo'
)
end
end
context
'when a private snippet is made public'
do
let
(
:visibility_level
)
{
Snippet
::
PRIVATE
}
it
'rejects the snippet'
do
expect
{
update_snippet
(
title:
'Foo'
,
visibility_level:
Snippet
::
PUBLIC
)
}.
not_to
change
{
snippet
.
reload
.
title
}
end
it
'creates a spam log'
do
expect
{
update_snippet
(
title:
'Foo'
,
visibility_level:
Snippet
::
PUBLIC
)
}.
to
change
{
SpamLog
.
count
}.
by
(
1
)
end
it
'renders :edit with recaptcha disabled'
do
stub_application_setting
(
recaptcha_enabled:
false
)
update_snippet
(
title:
'Foo'
,
visibility_level:
Snippet
::
PUBLIC
)
expect
(
response
).
to
render_template
(
:edit
)
end
context
'recaptcha enabled'
do
before
do
stub_application_setting
(
recaptcha_enabled:
true
)
end
it
'renders :verify with recaptcha enabled'
do
update_snippet
(
title:
'Foo'
,
visibility_level:
Snippet
::
PUBLIC
)
expect
(
response
).
to
render_template
(
:verify
)
end
it
'renders snippet page when recaptcha verified'
do
spammy_title
=
'Whatever'
spam_logs
=
create_list
(
:spam_log
,
2
,
user:
user
,
title:
spammy_title
)
snippet
=
update_snippet
({
title:
spammy_title
,
visibility_level:
Snippet
::
PUBLIC
},
{
spam_log_id:
spam_logs
.
last
.
id
,
recaptcha_verification:
true
})
expect
(
response
).
to
redirect_to
(
snippet
)
end
end
end
context
'when the snippet is public'
do
let
(
:visibility_level
)
{
Snippet
::
PUBLIC
}
it
'rejects the shippet'
do
expect
{
update_snippet
(
title:
'Foo'
)
}.
not_to
change
{
snippet
.
reload
.
title
}
end
it
'creates a spam log'
do
expect
{
update_snippet
(
title:
'Foo'
)
}.
to
change
{
SpamLog
.
count
}.
by
(
1
)
end
it
'renders :edit with recaptcha disabled'
do
stub_application_setting
(
recaptcha_enabled:
false
)
update_snippet
(
title:
'Foo'
)
expect
(
response
).
to
render_template
(
:edit
)
end
context
'recaptcha enabled'
do
before
do
stub_application_setting
(
recaptcha_enabled:
true
)
end
it
'renders :verify with recaptcha enabled'
do
update_snippet
(
title:
'Foo'
)
expect
(
response
).
to
render_template
(
:verify
)
end
it
'renders snippet page when recaptcha verified'
do
spammy_title
=
'Whatever'
spam_logs
=
create_list
(
:spam_log
,
2
,
user:
user
,
title:
spammy_title
)
snippet
=
update_snippet
({
title:
spammy_title
},
{
spam_log_id:
spam_logs
.
last
.
id
,
recaptcha_verification:
true
})
expect
(
response
).
to
redirect_to
(
snippet_path
(
snippet
))
end
end
end
end
end
end
end
end
...
...
spec/models/concerns/spammable_spec.rb
View file @
2ace39f2
...
@@ -23,6 +23,7 @@ describe Issue, 'Spammable' do
...
@@ -23,6 +23,7 @@ describe Issue, 'Spammable' do
describe
'#check_for_spam?'
do
describe
'#check_for_spam?'
do
it
'returns true for public project'
do
it
'returns true for public project'
do
issue
.
project
.
update_attribute
(
:visibility_level
,
Gitlab
::
VisibilityLevel
::
PUBLIC
)
issue
.
project
.
update_attribute
(
:visibility_level
,
Gitlab
::
VisibilityLevel
::
PUBLIC
)
expect
(
issue
.
check_for_spam?
).
to
eq
(
true
)
expect
(
issue
.
check_for_spam?
).
to
eq
(
true
)
end
end
...
...
spec/requests/api/issues_spec.rb
View file @
2ace39f2
...
@@ -1028,6 +1028,33 @@ describe API::Issues, api: true do
...
@@ -1028,6 +1028,33 @@ describe API::Issues, api: true do
end
end
end
end
describe
'PUT /projects/:id/issues/:issue_id with spam filtering'
do
let
(
:params
)
do
{
title:
'updated title'
,
description:
'content here'
,
labels:
'label, label2'
}
end
it
"does not create a new project issue"
do
allow_any_instance_of
(
SpamService
).
to
receive_messages
(
check_for_spam?:
true
)
allow_any_instance_of
(
AkismetService
).
to
receive_messages
(
is_spam?:
true
)
put
api
(
"/projects/
#{
project
.
id
}
/issues/
#{
issue
.
id
}
"
,
user
),
params
expect
(
response
).
to
have_http_status
(
400
)
expect
(
json_response
[
'message'
]).
to
eq
({
"error"
=>
"Spam detected"
})
spam_logs
=
SpamLog
.
all
expect
(
spam_logs
.
count
).
to
eq
(
1
)
expect
(
spam_logs
[
0
].
title
).
to
eq
(
'updated title'
)
expect
(
spam_logs
[
0
].
description
).
to
eq
(
'content here'
)
expect
(
spam_logs
[
0
].
user
).
to
eq
(
user
)
expect
(
spam_logs
[
0
].
noteable_type
).
to
eq
(
'Issue'
)
end
end
describe
'PUT /projects/:id/issues/:issue_id to update labels'
do
describe
'PUT /projects/:id/issues/:issue_id to update labels'
do
let!
(
:label
)
{
create
(
:label
,
title:
'dummy'
,
project:
project
)
}
let!
(
:label
)
{
create
(
:label
,
title:
'dummy'
,
project:
project
)
}
let!
(
:label_link
)
{
create
(
:label_link
,
label:
label
,
target:
issue
)
}
let!
(
:label_link
)
{
create
(
:label_link
,
label:
label
,
target:
issue
)
}
...
...
spec/requests/api/project_snippets_spec.rb
View file @
2ace39f2
...
@@ -78,43 +78,33 @@ describe API::ProjectSnippets, api: true do
...
@@ -78,43 +78,33 @@ describe API::ProjectSnippets, api: true do
allow_any_instance_of
(
AkismetService
).
to
receive
(
:is_spam?
).
and_return
(
true
)
allow_any_instance_of
(
AkismetService
).
to
receive
(
:is_spam?
).
and_return
(
true
)
end
end
context
'when the project is private'
do
context
'when the snippet is private'
do
let
(
:private_project
)
{
create
(
:project_empty_repo
,
:private
)
}
it
'creates the snippet'
do
expect
{
create_snippet
(
project
,
visibility_level:
Snippet
::
PRIVATE
)
}.
context
'when the snippet is public'
do
to
change
{
Snippet
.
count
}.
by
(
1
)
it
'creates the snippet'
do
expect
{
create_snippet
(
private_project
,
visibility_level:
Snippet
::
PUBLIC
)
}.
to
change
{
Snippet
.
count
}.
by
(
1
)
end
end
end
end
end
context
'when the project is public'
do
context
'when the snippet is public'
do
context
'when the snippet is private'
do
it
'rejects the shippet'
do
it
'creates the snippet'
do
expect
{
create_snippet
(
project
,
visibility_level:
Snippet
::
PUBLIC
)
}.
expect
{
create_snippet
(
project
,
visibility_level:
Snippet
::
PRIVATE
)
}.
not_to
change
{
Snippet
.
count
}
to
change
{
Snippet
.
count
}.
by
(
1
)
end
expect
(
response
).
to
have_http_status
(
400
)
expect
(
json_response
[
'message'
]).
to
eq
({
"error"
=>
"Spam detected"
})
end
end
context
'when the snippet is public'
do
it
'creates a spam log'
do
it
'rejects the shippet'
do
expect
{
create_snippet
(
project
,
visibility_level:
Snippet
::
PUBLIC
)
}.
expect
{
create_snippet
(
project
,
visibility_level:
Snippet
::
PUBLIC
)
}.
to
change
{
SpamLog
.
count
}.
by
(
1
)
not_to
change
{
Snippet
.
count
}
expect
(
response
).
to
have_http_status
(
400
)
end
it
'creates a spam log'
do
expect
{
create_snippet
(
project
,
visibility_level:
Snippet
::
PUBLIC
)
}.
to
change
{
SpamLog
.
count
}.
by
(
1
)
end
end
end
end
end
end
end
end
end
describe
'PUT /projects/:project_id/snippets/:id/'
do
describe
'PUT /projects/:project_id/snippets/:id/'
do
let
(
:snippet
)
{
create
(
:project_snippet
,
author:
admin
)
}
let
(
:visibility_level
)
{
Snippet
::
PUBLIC
}
let
(
:snippet
)
{
create
(
:project_snippet
,
author:
admin
,
visibility_level:
visibility_level
)
}
it
'updates snippet'
do
it
'updates snippet'
do
new_content
=
'New content'
new_content
=
'New content'
...
@@ -138,6 +128,56 @@ describe API::ProjectSnippets, api: true do
...
@@ -138,6 +128,56 @@ describe API::ProjectSnippets, api: true do
expect
(
response
).
to
have_http_status
(
400
)
expect
(
response
).
to
have_http_status
(
400
)
end
end
context
'when the snippet is spam'
do
def
update_snippet
(
snippet_params
=
{})
put
api
(
"/projects/
#{
snippet
.
project
.
id
}
/snippets/
#{
snippet
.
id
}
"
,
admin
),
snippet_params
end
before
do
allow_any_instance_of
(
AkismetService
).
to
receive
(
:is_spam?
).
and_return
(
true
)
end
context
'when the snippet is private'
do
let
(
:visibility_level
)
{
Snippet
::
PRIVATE
}
it
'creates the snippet'
do
expect
{
update_snippet
(
title:
'Foo'
)
}.
to
change
{
snippet
.
reload
.
title
}.
to
(
'Foo'
)
end
end
context
'when the snippet is public'
do
let
(
:visibility_level
)
{
Snippet
::
PUBLIC
}
it
'rejects the snippet'
do
expect
{
update_snippet
(
title:
'Foo'
)
}.
not_to
change
{
snippet
.
reload
.
title
}
end
it
'creates a spam log'
do
expect
{
update_snippet
(
title:
'Foo'
)
}.
to
change
{
SpamLog
.
count
}.
by
(
1
)
end
end
context
'when the private snippet is made public'
do
let
(
:visibility_level
)
{
Snippet
::
PRIVATE
}
it
'rejects the snippet'
do
expect
{
update_snippet
(
title:
'Foo'
,
visibility_level:
Snippet
::
PUBLIC
)
}.
not_to
change
{
snippet
.
reload
.
title
}
expect
(
response
).
to
have_http_status
(
400
)
expect
(
json_response
[
'message'
]).
to
eq
({
"error"
=>
"Spam detected"
})
end
it
'creates a spam log'
do
expect
{
update_snippet
(
title:
'Foo'
,
visibility_level:
Snippet
::
PUBLIC
)
}.
to
change
{
SpamLog
.
count
}.
by
(
1
)
end
end
end
end
end
describe
'DELETE /projects/:project_id/snippets/:id/'
do
describe
'DELETE /projects/:project_id/snippets/:id/'
do
...
...
spec/requests/api/snippets_spec.rb
View file @
2ace39f2
...
@@ -129,7 +129,9 @@ describe API::Snippets, api: true do
...
@@ -129,7 +129,9 @@ describe API::Snippets, api: true do
it
'rejects the shippet'
do
it
'rejects the shippet'
do
expect
{
create_snippet
(
visibility_level:
Snippet
::
PUBLIC
)
}.
expect
{
create_snippet
(
visibility_level:
Snippet
::
PUBLIC
)
}.
not_to
change
{
Snippet
.
count
}
not_to
change
{
Snippet
.
count
}
expect
(
response
).
to
have_http_status
(
400
)
expect
(
response
).
to
have_http_status
(
400
)
expect
(
json_response
[
'message'
]).
to
eq
({
"error"
=>
"Spam detected"
})
end
end
it
'creates a spam log'
do
it
'creates a spam log'
do
...
@@ -141,16 +143,20 @@ describe API::Snippets, api: true do
...
@@ -141,16 +143,20 @@ describe API::Snippets, api: true do
end
end
describe
'PUT /snippets/:id'
do
describe
'PUT /snippets/:id'
do
let
(
:visibility_level
)
{
Snippet
::
PUBLIC
}
let
(
:other_user
)
{
create
(
:user
)
}
let
(
:other_user
)
{
create
(
:user
)
}
let
(
:public_snippet
)
{
create
(
:personal_snippet
,
:public
,
author:
user
)
}
let
(
:snippet
)
do
create
(
:personal_snippet
,
author:
user
,
visibility_level:
visibility_level
)
end
it
'updates snippet'
do
it
'updates snippet'
do
new_content
=
'New content'
new_content
=
'New content'
put
api
(
"/snippets/
#{
public_
snippet
.
id
}
"
,
user
),
content:
new_content
put
api
(
"/snippets/
#{
snippet
.
id
}
"
,
user
),
content:
new_content
expect
(
response
).
to
have_http_status
(
200
)
expect
(
response
).
to
have_http_status
(
200
)
public_
snippet
.
reload
snippet
.
reload
expect
(
public_
snippet
.
content
).
to
eq
(
new_content
)
expect
(
snippet
.
content
).
to
eq
(
new_content
)
end
end
it
'returns 404 for invalid snippet id'
do
it
'returns 404 for invalid snippet id'
do
...
@@ -161,7 +167,7 @@ describe API::Snippets, api: true do
...
@@ -161,7 +167,7 @@ describe API::Snippets, api: true do
end
end
it
"returns 404 for another user's snippet"
do
it
"returns 404 for another user's snippet"
do
put
api
(
"/snippets/
#{
public_
snippet
.
id
}
"
,
other_user
),
title:
'fubar'
put
api
(
"/snippets/
#{
snippet
.
id
}
"
,
other_user
),
title:
'fubar'
expect
(
response
).
to
have_http_status
(
404
)
expect
(
response
).
to
have_http_status
(
404
)
expect
(
json_response
[
'message'
]).
to
eq
(
'404 Snippet Not Found'
)
expect
(
json_response
[
'message'
]).
to
eq
(
'404 Snippet Not Found'
)
...
@@ -172,6 +178,56 @@ describe API::Snippets, api: true do
...
@@ -172,6 +178,56 @@ describe API::Snippets, api: true do
expect
(
response
).
to
have_http_status
(
400
)
expect
(
response
).
to
have_http_status
(
400
)
end
end
context
'when the snippet is spam'
do
def
update_snippet
(
snippet_params
=
{})
put
api
(
"/snippets/
#{
snippet
.
id
}
"
,
user
),
snippet_params
end
before
do
allow_any_instance_of
(
AkismetService
).
to
receive
(
:is_spam?
).
and_return
(
true
)
end
context
'when the snippet is private'
do
let
(
:visibility_level
)
{
Snippet
::
PRIVATE
}
it
'updates the snippet'
do
expect
{
update_snippet
(
title:
'Foo'
)
}.
to
change
{
snippet
.
reload
.
title
}.
to
(
'Foo'
)
end
end
context
'when the snippet is public'
do
let
(
:visibility_level
)
{
Snippet
::
PUBLIC
}
it
'rejects the shippet'
do
expect
{
update_snippet
(
title:
'Foo'
)
}.
not_to
change
{
snippet
.
reload
.
title
}
expect
(
response
).
to
have_http_status
(
400
)
expect
(
json_response
[
'message'
]).
to
eq
({
"error"
=>
"Spam detected"
})
end
it
'creates a spam log'
do
expect
{
update_snippet
(
title:
'Foo'
)
}.
to
change
{
SpamLog
.
count
}.
by
(
1
)
end
end
context
'when a private snippet is made public'
do
let
(
:visibility_level
)
{
Snippet
::
PRIVATE
}
it
'rejects the snippet'
do
expect
{
update_snippet
(
title:
'Foo'
,
visibility_level:
Snippet
::
PUBLIC
)
}.
not_to
change
{
snippet
.
reload
.
title
}
end
it
'creates a spam log'
do
expect
{
update_snippet
(
title:
'Foo'
,
visibility_level:
Snippet
::
PUBLIC
)
}.
to
change
{
SpamLog
.
count
}.
by
(
1
)
end
end
end
end
end
describe
'DELETE /snippets/:id'
do
describe
'DELETE /snippets/:id'
do
...
...
spec/requests/api/v3/issues_spec.rb
View file @
2ace39f2
...
@@ -986,6 +986,33 @@ describe API::V3::Issues, api: true do
...
@@ -986,6 +986,33 @@ describe API::V3::Issues, api: true do
end
end
end
end
describe
'PUT /projects/:id/issues/:issue_id with spam filtering'
do
let
(
:params
)
do
{
title:
'updated title'
,
description:
'content here'
,
labels:
'label, label2'
}
end
it
"does not create a new project issue"
do
allow_any_instance_of
(
SpamService
).
to
receive_messages
(
check_for_spam?:
true
)
allow_any_instance_of
(
AkismetService
).
to
receive_messages
(
is_spam?:
true
)
put
v3_api
(
"/projects/
#{
project
.
id
}
/issues/
#{
issue
.
id
}
"
,
user
),
params
expect
(
response
).
to
have_http_status
(
400
)
expect
(
json_response
[
'message'
]).
to
eq
({
"error"
=>
"Spam detected"
})
spam_logs
=
SpamLog
.
all
expect
(
spam_logs
.
count
).
to
eq
(
1
)
expect
(
spam_logs
[
0
].
title
).
to
eq
(
'updated title'
)
expect
(
spam_logs
[
0
].
description
).
to
eq
(
'content here'
)
expect
(
spam_logs
[
0
].
user
).
to
eq
(
user
)
expect
(
spam_logs
[
0
].
noteable_type
).
to
eq
(
'Issue'
)
end
end
describe
'PUT /projects/:id/issues/:issue_id to update labels'
do
describe
'PUT /projects/:id/issues/:issue_id to update labels'
do
let!
(
:label
)
{
create
(
:label
,
title:
'dummy'
,
project:
project
)
}
let!
(
:label
)
{
create
(
:label
,
title:
'dummy'
,
project:
project
)
}
let!
(
:label_link
)
{
create
(
:label_link
,
label:
label
,
target:
issue
)
}
let!
(
:label_link
)
{
create
(
:label_link
,
label:
label
,
target:
issue
)
}
...
...
spec/requests/api/v3/project_snippets_spec.rb
View file @
2ace39f2
...
@@ -85,43 +85,33 @@ describe API::ProjectSnippets, api: true do
...
@@ -85,43 +85,33 @@ describe API::ProjectSnippets, api: true do
allow_any_instance_of
(
AkismetService
).
to
receive
(
:is_spam?
).
and_return
(
true
)
allow_any_instance_of
(
AkismetService
).
to
receive
(
:is_spam?
).
and_return
(
true
)
end
end
context
'when the project is private'
do
context
'when the snippet is private'
do
let
(
:private_project
)
{
create
(
:project_empty_repo
,
:private
)
}
it
'creates the snippet'
do
expect
{
create_snippet
(
project
,
visibility_level:
Snippet
::
PRIVATE
)
}.
context
'when the snippet is public'
do
to
change
{
Snippet
.
count
}.
by
(
1
)
it
'creates the snippet'
do
expect
{
create_snippet
(
private_project
,
visibility_level:
Snippet
::
PUBLIC
)
}.
to
change
{
Snippet
.
count
}.
by
(
1
)
end
end
end
end
end
context
'when the project is public'
do
context
'when the snippet is public'
do
context
'when the snippet is private'
do
it
'rejects the shippet'
do
it
'creates the snippet'
do
expect
{
create_snippet
(
project
,
visibility_level:
Snippet
::
PUBLIC
)
}.
expect
{
create_snippet
(
project
,
visibility_level:
Snippet
::
PRIVATE
)
}.
not_to
change
{
Snippet
.
count
}
to
change
{
Snippet
.
count
}.
by
(
1
)
end
expect
(
response
).
to
have_http_status
(
400
)
expect
(
json_response
[
'message'
]).
to
eq
({
"error"
=>
"Spam detected"
})
end
end
context
'when the snippet is public'
do
it
'creates a spam log'
do
it
'rejects the shippet'
do
expect
{
create_snippet
(
project
,
visibility_level:
Snippet
::
PUBLIC
)
}.
expect
{
create_snippet
(
project
,
visibility_level:
Snippet
::
PUBLIC
)
}.
to
change
{
SpamLog
.
count
}.
by
(
1
)
not_to
change
{
Snippet
.
count
}
expect
(
response
).
to
have_http_status
(
400
)
end
it
'creates a spam log'
do
expect
{
create_snippet
(
project
,
visibility_level:
Snippet
::
PUBLIC
)
}.
to
change
{
SpamLog
.
count
}.
by
(
1
)
end
end
end
end
end
end
end
end
end
describe
'PUT /projects/:project_id/snippets/:id/'
do
describe
'PUT /projects/:project_id/snippets/:id/'
do
let
(
:snippet
)
{
create
(
:project_snippet
,
author:
admin
)
}
let
(
:visibility_level
)
{
Snippet
::
PUBLIC
}
let
(
:snippet
)
{
create
(
:project_snippet
,
author:
admin
,
visibility_level:
visibility_level
)
}
it
'updates snippet'
do
it
'updates snippet'
do
new_content
=
'New content'
new_content
=
'New content'
...
@@ -145,6 +135,56 @@ describe API::ProjectSnippets, api: true do
...
@@ -145,6 +135,56 @@ describe API::ProjectSnippets, api: true do
expect
(
response
).
to
have_http_status
(
400
)
expect
(
response
).
to
have_http_status
(
400
)
end
end
context
'when the snippet is spam'
do
def
update_snippet
(
snippet_params
=
{})
put
v3_api
(
"/projects/
#{
snippet
.
project
.
id
}
/snippets/
#{
snippet
.
id
}
"
,
admin
),
snippet_params
end
before
do
allow_any_instance_of
(
AkismetService
).
to
receive
(
:is_spam?
).
and_return
(
true
)
end
context
'when the snippet is private'
do
let
(
:visibility_level
)
{
Snippet
::
PRIVATE
}
it
'creates the snippet'
do
expect
{
update_snippet
(
title:
'Foo'
)
}.
to
change
{
snippet
.
reload
.
title
}.
to
(
'Foo'
)
end
end
context
'when the snippet is public'
do
let
(
:visibility_level
)
{
Snippet
::
PUBLIC
}
it
'rejects the snippet'
do
expect
{
update_snippet
(
title:
'Foo'
)
}.
not_to
change
{
snippet
.
reload
.
title
}
end
it
'creates a spam log'
do
expect
{
update_snippet
(
title:
'Foo'
)
}.
to
change
{
SpamLog
.
count
}.
by
(
1
)
end
end
context
'when the private snippet is made public'
do
let
(
:visibility_level
)
{
Snippet
::
PRIVATE
}
it
'rejects the snippet'
do
expect
{
update_snippet
(
title:
'Foo'
,
visibility_level:
Snippet
::
PUBLIC
)
}.
not_to
change
{
snippet
.
reload
.
title
}
expect
(
response
).
to
have_http_status
(
400
)
expect
(
json_response
[
'message'
]).
to
eq
({
"error"
=>
"Spam detected"
})
end
it
'creates a spam log'
do
expect
{
update_snippet
(
title:
'Foo'
,
visibility_level:
Snippet
::
PUBLIC
)
}.
to
change
{
SpamLog
.
count
}.
by
(
1
)
end
end
end
end
end
describe
'DELETE /projects/:project_id/snippets/:id/'
do
describe
'DELETE /projects/:project_id/snippets/:id/'
do
...
...
spec/services/issues/create_service_spec.rb
View file @
2ace39f2
...
@@ -230,16 +230,6 @@ describe Issues::CreateService, services: true do
...
@@ -230,16 +230,6 @@ describe Issues::CreateService, services: true do
expect
{
issue
}.
not_to
change
{
SpamLog
.
last
.
recaptcha_verified
}
expect
{
issue
}.
not_to
change
{
SpamLog
.
last
.
recaptcha_verified
}
end
end
end
end
context
'when spam log title does not match the issue title'
do
before
do
opts
[
:title
]
=
'Another issue'
end
it
'does not mark spam_log as recaptcha_verified'
do
expect
{
issue
}.
not_to
change
{
SpamLog
.
last
.
recaptcha_verified
}
end
end
end
end
context
'when recaptcha was not verified'
do
context
'when recaptcha was not verified'
do
...
...
spec/services/spam_service_spec.rb
View file @
2ace39f2
require
'spec_helper'
require
'spec_helper'
describe
SpamService
,
services:
true
do
describe
SpamService
,
services:
true
do
describe
'#check'
do
describe
'#when_recaptcha_verified'
do
let
(
:project
)
{
create
(
:project
,
:public
)
}
def
check_spam
(
issue
,
request
,
recaptcha_verified
)
let
(
:issue
)
{
create
(
:issue
,
project:
project
)
}
described_class
.
new
(
issue
,
request
).
when_recaptcha_verified
(
recaptcha_verified
)
do
let
(
:request
)
{
double
(
:request
,
env:
{})
}
'yielded'
end
end
it
'yields block when recaptcha was already verified'
do
issue
=
build_stubbed
(
:issue
)
def
check_spam
(
issue
,
request
)
expect
(
check_spam
(
issue
,
nil
,
true
)).
to
eql
(
'yielded'
)
described_class
.
new
(
issue
,
request
).
check
end
end
context
'when indicated as spam by akismet'
do
context
'when recaptcha was not verified'
do
before
{
allow
(
AkismetService
).
to
receive
(
:new
).
and_return
(
double
(
is_spam?:
true
))
}
let
(
:project
)
{
create
(
:project
,
:public
)
}
let
(
:issue
)
{
create
(
:issue
,
project:
project
)
}
let
(
:request
)
{
double
(
:request
,
env:
{})
}
it
'returns false when request is missing'
do
context
'when indicated as spam by akismet'
do
expect
(
check_spam
(
issue
,
nil
)).
to
be_falsey
before
{
allow
(
AkismetService
).
to
receive
(
:new
).
and_return
(
double
(
is_spam?:
true
))
}
end
it
'returns false when issue is not public
'
do
it
'doesnt check as spam when request is missing
'
do
issue
=
create
(
:issue
,
project:
create
(
:project
,
:private
)
)
check_spam
(
issue
,
nil
,
false
)
expect
(
check_spam
(
issue
,
request
)
).
to
be_falsey
expect
(
issue
.
spam
).
to
be_falsey
end
end
it
'returns true'
do
it
'checks as spam'
do
expect
(
check_spam
(
issue
,
request
)).
to
be_truthy
check_spam
(
issue
,
request
,
false
)
end
it
'creates a spam log'
do
expect
(
issue
.
spam
).
to
be_truthy
expect
{
check_spam
(
issue
,
request
)
}.
to
change
{
SpamLog
.
count
}.
from
(
0
).
to
(
1
)
end
end
end
context
'when not indicated as spam by akismet'
do
it
'creates a spam log'
do
before
{
allow
(
AkismetService
).
to
receive
(
:new
).
and_return
(
double
(
is_spam?:
false
))
}
expect
{
check_spam
(
issue
,
request
,
false
)
}
.
to
change
{
SpamLog
.
count
}.
from
(
0
).
to
(
1
)
end
it
'returns false'
do
it
'doesnt yield block'
do
expect
(
check_spam
(
issue
,
request
)).
to
be_falsey
expect
(
check_spam
(
issue
,
request
,
false
))
.
to
eql
(
SpamLog
.
last
)
end
end
end
it
'does not create a spam log'
do
context
'when not indicated as spam by akismet'
do
expect
{
check_spam
(
issue
,
request
)
}.
not_to
change
{
SpamLog
.
count
}
before
{
allow
(
AkismetService
).
to
receive
(
:new
).
and_return
(
double
(
is_spam?:
false
))
}
it
'returns false'
do
expect
(
check_spam
(
issue
,
request
,
false
)).
to
be_falsey
end
it
'does not create a spam log'
do
expect
{
check_spam
(
issue
,
request
,
false
)
}
.
not_to
change
{
SpamLog
.
count
}
end
end
end
end
end
end
end
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment