Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Pleroma
pleroma
Commits
fa1f11e8
Commit
fa1f11e8
authored
Nov 03, 2017
by
lain
Browse files
Merge branch 'feature/blocks' into 'develop'
Feature/blocks See merge request
!5
parents
8a1a7191
c6b9b777
Pipeline
#22
passed with stage
in 1 minute and 51 seconds
Changes
12
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
lib/pleroma/notification.ex
View file @
fa1f11e8
...
...
@@ -46,9 +46,11 @@ def create_notifications(_), do: {:ok, []}
# TODO move to sql, too.
def
create_notification
(%
Activity
{}
=
activity
,
%
User
{}
=
user
)
do
notification
=
%
Notification
{
user_id:
user
.
id
,
activity_id:
activity
.
id
}
{
:ok
,
notification
}
=
Repo
.
insert
(
notification
)
notification
unless
User
.
blocks?
(
user
,
%{
ap_id:
activity
.
data
[
"actor"
]})
do
notification
=
%
Notification
{
user_id:
user
.
id
,
activity_id:
activity
.
id
}
{
:ok
,
notification
}
=
Repo
.
insert
(
notification
)
notification
end
end
end
lib/pleroma/user.ex
View file @
fa1f11e8
...
...
@@ -293,4 +293,28 @@ def search(query, resolve) do
limit:
20
Repo
.
all
(
q
)
end
def
block
(
user
,
%{
ap_id:
ap_id
})
do
blocks
=
user
.
info
[
"blocks"
]
||
[]
new_blocks
=
Enum
.
uniq
([
ap_id
|
blocks
])
new_info
=
Map
.
put
(
user
.
info
,
"blocks"
,
new_blocks
)
cs
=
User
.
info_changeset
(
user
,
%{
info:
new_info
})
Repo
.
update
(
cs
)
end
def
unblock
(
user
,
%{
ap_id:
ap_id
})
do
blocks
=
user
.
info
[
"blocks"
]
||
[]
new_blocks
=
List
.
delete
(
blocks
,
ap_id
)
new_info
=
Map
.
put
(
user
.
info
,
"blocks"
,
new_blocks
)
cs
=
User
.
info_changeset
(
user
,
%{
info:
new_info
})
Repo
.
update
(
cs
)
end
def
blocks?
(
user
,
%{
ap_id:
ap_id
})
do
blocks
=
user
.
info
[
"blocks"
]
||
[]
Enum
.
member?
(
blocks
,
ap_id
)
end
end
lib/pleroma/web/activity_pub/activity_pub.ex
View file @
fa1f11e8
...
...
@@ -93,10 +93,11 @@ def delete(%Object{data: %{"id" => id, "actor" => actor}} = object, local \\ tru
end
end
def
fetch_activities_for_context
(
context
)
do
def
fetch_activities_for_context
(
context
,
opts
\\
%{}
)
do
query
=
from
activity
in
Activity
,
where:
fragment
(
"?->>'type' = ? and ?->>'context' = ?"
,
activity
.
data
,
"Create"
,
activity
.
data
,
^
context
),
order_by:
[
desc:
:id
]
query
=
restrict_blocked
(
query
,
opts
)
Repo
.
all
(
query
)
end
...
...
@@ -163,6 +164,13 @@ defp restrict_recent(query, _) do
where:
activity
.
id
>
^
since
end
defp
restrict_blocked
(
query
,
%{
"blocking_user"
=>
%
User
{
info:
info
}})
do
blocks
=
info
[
"blocks"
]
||
[]
from
activity
in
query
,
where:
fragment
(
"not (?->>'actor' = ANY(?))"
,
activity
.
data
,
^
blocks
)
end
defp
restrict_blocked
(
query
,
_
),
do
:
query
def
fetch_activities
(
recipients
,
opts
\\
%{})
do
base_query
=
from
activity
in
Activity
,
limit:
20
,
...
...
@@ -178,6 +186,7 @@ def fetch_activities(recipients, opts \\ %{}) do
|>
restrict_type
(
opts
)
|>
restrict_favorited_by
(
opts
)
|>
restrict_recent
(
opts
)
|>
restrict_blocked
(
opts
)
|>
Repo
.
all
|>
Enum
.
reverse
end
...
...
lib/pleroma/web/mastodon_api/mastodon_api_controller.ex
View file @
fa1f11e8
...
...
@@ -79,6 +79,7 @@ defp add_link_headers(conn, method, activities) do
def
home_timeline
(%{
assigns:
%{
user:
user
}}
=
conn
,
params
)
do
params
=
params
|>
Map
.
put
(
"type"
,
[
"Create"
,
"Announce"
])
|>
Map
.
put
(
"blocking_user"
,
user
)
activities
=
ActivityPub
.
fetch_activities
([
user
.
ap_id
|
user
.
following
],
params
)
|>
Enum
.
reverse
...
...
@@ -92,6 +93,7 @@ def public_timeline(%{assigns: %{user: user}} = conn, params) do
params
=
params
|>
Map
.
put
(
"type"
,
[
"Create"
,
"Announce"
])
|>
Map
.
put
(
"local_only"
,
!!params
[
"local"
])
|>
Map
.
put
(
"blocking_user"
,
user
)
activities
=
ActivityPub
.
fetch_public_activities
(
params
)
|>
Enum
.
reverse
...
...
@@ -123,7 +125,7 @@ def get_status(%{assigns: %{user: user}} = conn, %{"id" => id}) do
def
get_context
(%{
assigns:
%{
user:
user
}}
=
conn
,
%{
"id"
=>
id
})
do
with
%
Activity
{}
=
activity
<-
Repo
.
get
(
Activity
,
id
),
activities
<-
ActivityPub
.
fetch_activities_for_context
(
activity
.
data
[
"object"
][
"context"
]),
activities
<-
ActivityPub
.
fetch_activities_for_context
(
activity
.
data
[
"object"
][
"context"
]
,
%{
"blocking_user"
=>
user
}
),
activities
<-
activities
|>
Enum
.
filter
(
fn
(%{
id:
aid
})
->
to_string
(
aid
)
!=
to_string
(
id
)
end
),
grouped_activities
<-
Enum
.
group_by
(
activities
,
fn
(%{
id:
id
})
->
id
<
activity
.
id
end
)
do
result
=
%{
...
...
@@ -246,6 +248,7 @@ def hashtag_timeline(%{assigns: %{user: user}} = conn, params) do
params
=
params
|>
Map
.
put
(
"type"
,
"Create"
)
|>
Map
.
put
(
"local_only"
,
!!params
[
"local"
])
|>
Map
.
put
(
"blocking_user"
,
user
)
activities
=
ActivityPub
.
fetch_public_activities
(
params
)
|>
Enum
.
reverse
...
...
@@ -308,6 +311,39 @@ def unfollow(%{assigns: %{user: follower}} = conn, %{"id" => id}) do
end
end
def
block
(%{
assigns:
%{
user:
blocker
}}
=
conn
,
%{
"id"
=>
id
})
do
with
%
User
{}
=
blocked
<-
Repo
.
get
(
User
,
id
),
{
:ok
,
blocker
}
<-
User
.
block
(
blocker
,
blocked
)
do
render
conn
,
AccountView
,
"relationship.json"
,
%{
user:
blocker
,
target:
blocked
}
else
{
:error
,
message
}
=
err
->
conn
|>
put_resp_content_type
(
"application/json"
)
|>
send_resp
(
403
,
Poison
.
encode!
(%{
"error"
=>
message
}))
end
end
def
unblock
(%{
assigns:
%{
user:
blocker
}}
=
conn
,
%{
"id"
=>
id
})
do
with
%
User
{}
=
blocked
<-
Repo
.
get
(
User
,
id
),
{
:ok
,
blocker
}
<-
User
.
unblock
(
blocker
,
blocked
)
do
render
conn
,
AccountView
,
"relationship.json"
,
%{
user:
blocker
,
target:
blocked
}
else
{
:error
,
message
}
=
err
->
conn
|>
put_resp_content_type
(
"application/json"
)
|>
send_resp
(
403
,
Poison
.
encode!
(%{
"error"
=>
message
}))
end
end
# TODO: Use proper query
def
blocks
(%{
assigns:
%{
user:
user
}}
=
conn
,
_
)
do
with
blocked_users
<-
user
.
info
[
"blocks"
]
||
[],
accounts
<-
Enum
.
map
(
blocked_users
,
fn
(
ap_id
)
->
User
.
get_cached_by_ap_id
(
ap_id
)
end
)
do
res
=
AccountView
.
render
(
"accounts.json"
,
users:
accounts
,
for:
user
,
as:
:user
)
json
(
conn
,
res
)
end
end
def
search
(%{
assigns:
%{
user:
user
}}
=
conn
,
%{
"q"
=>
query
}
=
params
)
do
accounts
=
User
.
search
(
query
,
params
[
"resolve"
]
==
"true"
)
...
...
@@ -338,6 +374,7 @@ def favourites(%{assigns: %{user: user}} = conn, params) do
params
=
conn
|>
Map
.
put
(
"type"
,
"Create"
)
|>
Map
.
put
(
"favorited_by"
,
user
.
ap_id
)
|>
Map
.
put
(
"blocking_user"
,
user
)
activities
=
ActivityPub
.
fetch_activities
([],
params
)
|>
Enum
.
reverse
...
...
lib/pleroma/web/mastodon_api/views/account_view.ex
View file @
fa1f11e8
...
...
@@ -55,7 +55,7 @@ def render("relationship.json", %{user: user, target: target}) do
id:
target
.
id
,
following:
User
.
following?
(
user
,
target
),
followed_by:
User
.
following?
(
target
,
user
),
blocking:
false
,
blocking:
User
.
blocks?
(
user
,
target
)
,
muting:
false
,
requested:
false
,
domain_blocking:
false
...
...
lib/pleroma/web/router.ex
View file @
fa1f11e8
...
...
@@ -58,14 +58,15 @@ def user_fetcher(username) do
get
"/accounts/search"
,
MastodonAPIController
,
:account_search
post
"/accounts/:id/follow"
,
MastodonAPIController
,
:follow
post
"/accounts/:id/unfollow"
,
MastodonAPIController
,
:unfollow
post
"/accounts/:id/block"
,
MastodonAPIController
,
:
relationship_noop
post
"/accounts/:id/unblock"
,
MastodonAPIController
,
:
relationship_noop
post
"/accounts/:id/block"
,
MastodonAPIController
,
:
block
post
"/accounts/:id/unblock"
,
MastodonAPIController
,
:
unblock
post
"/accounts/:id/mute"
,
MastodonAPIController
,
:relationship_noop
post
"/accounts/:id/unmute"
,
MastodonAPIController
,
:relationship_noop
post
"/follows"
,
MastodonAPIController
,
:follow
get
"/blocks"
,
MastodonAPIController
,
:empty_array
get
"/blocks"
,
MastodonAPIController
,
:blocks
get
"/domain_blocks"
,
MastodonAPIController
,
:empty_array
get
"/follow_requests"
,
MastodonAPIController
,
:empty_array
get
"/mutes"
,
MastodonAPIController
,
:empty_array
...
...
lib/pleroma/web/twitter_api/twitter_api.ex
View file @
fa1f11e8
...
...
@@ -14,17 +14,20 @@ def create_status(%User{} = user, %{"status" => status} = data) do
end
def
fetch_friend_statuses
(
user
,
opts
\\
%{})
do
opts
=
Map
.
put
(
opts
,
"blocking_user"
,
user
)
ActivityPub
.
fetch_activities
([
user
.
ap_id
|
user
.
following
],
opts
)
|>
activities_to_statuses
(%{
for:
user
})
end
def
fetch_public_statuses
(
user
,
opts
\\
%{})
do
opts
=
Map
.
put
(
opts
,
"local_only"
,
true
)
opts
=
Map
.
put
(
opts
,
"blocking_user"
,
user
)
ActivityPub
.
fetch_public_activities
(
opts
)
|>
activities_to_statuses
(%{
for:
user
})
end
def
fetch_public_and_external_statuses
(
user
,
opts
\\
%{})
do
opts
=
Map
.
put
(
opts
,
"blocking_user"
,
user
)
ActivityPub
.
fetch_public_activities
(
opts
)
|>
activities_to_statuses
(%{
for:
user
})
end
...
...
@@ -41,7 +44,7 @@ def fetch_mentions(user, opts \\ %{}) do
def
fetch_conversation
(
user
,
id
)
do
with
context
when
is_binary
(
context
)
<-
conversation_id_to_context
(
id
),
activities
<-
ActivityPub
.
fetch_activities_for_context
(
context
),
activities
<-
ActivityPub
.
fetch_activities_for_context
(
context
,
%{
"blocking_user"
=>
user
}
),
statuses
<-
activities
|>
activities_to_statuses
(%{
for:
user
})
do
statuses
...
...
test/notification_test.exs
View file @
fa1f11e8
...
...
@@ -20,4 +20,15 @@ test "notifies someone when they are directly addressed" do
assert
other_notification
.
activity_id
==
activity
.
id
end
end
describe
"create_notification"
do
test
"it doesn't create a notification for user if the user blocks the activity author"
do
activity
=
insert
(
:note_activity
)
author
=
User
.
get_by_ap_id
(
activity
.
data
[
"actor"
])
user
=
insert
(
:user
)
{
:ok
,
user
}
=
User
.
block
(
user
,
author
)
assert
nil
==
Notification
.
create_notification
(
activity
,
user
)
end
end
end
test/user_test.exs
View file @
fa1f11e8
...
...
@@ -9,11 +9,6 @@ defmodule Pleroma.UserTest do
import
Ecto
.
Query
test
"ap_id returns the activity pub id for the user"
do
host
=
Application
.
get_env
(
:pleroma
,
Pleroma
.
Web
.
Endpoint
)
|>
Keyword
.
fetch!
(
:url
)
|>
Keyword
.
fetch!
(
:host
)
user
=
UserBuilder
.
build
expected_ap_id
=
"
#{
Pleroma
.
Web
.
base_url
}
/users/
#{
user
.
nickname
}
"
...
...
@@ -213,7 +208,9 @@ test "gets all followers for a given user" do
{
:ok
,
res
}
=
User
.
get_followers
(
user
)
assert
res
==
[
follower_one
,
follower_two
]
assert
Enum
.
member?
(
res
,
follower_one
)
assert
Enum
.
member?
(
res
,
follower_two
)
refute
Enum
.
member?
(
res
,
not_follower
)
end
test
"gets all friends (followed users) for a given user"
do
...
...
@@ -229,7 +226,9 @@ test "gets all friends (followed users) for a given user" do
followed_one
=
User
.
get_by_ap_id
(
followed_one
.
ap_id
)
followed_two
=
User
.
get_by_ap_id
(
followed_two
.
ap_id
)
assert
res
==
[
followed_one
,
followed_two
]
assert
Enum
.
member?
(
res
,
followed_one
)
assert
Enum
.
member?
(
res
,
followed_two
)
refute
Enum
.
member?
(
res
,
not_followed
)
end
end
...
...
@@ -274,5 +273,28 @@ test "it sets the info->follower_count property" do
assert
user
.
info
[
"follower_count"
]
==
1
end
end
describe
"blocks"
do
test
"it blocks people"
do
user
=
insert
(
:user
)
blocked_user
=
insert
(
:user
)
refute
User
.
blocks?
(
user
,
blocked_user
)
{
:ok
,
user
}
=
User
.
block
(
user
,
blocked_user
)
assert
User
.
blocks?
(
user
,
blocked_user
)
end
test
"it unblocks users"
do
user
=
insert
(
:user
)
blocked_user
=
insert
(
:user
)
{
:ok
,
user
}
=
User
.
block
(
user
,
blocked_user
)
{
:ok
,
user
}
=
User
.
unblock
(
user
,
blocked_user
)
refute
User
.
blocks?
(
user
,
blocked_user
)
end
end
end
test/web/activity_pub/activity_pub_test.exs
View file @
fa1f11e8
...
...
@@ -73,13 +73,40 @@ test "retrieves activities that have a given context" do
{
:ok
,
activity_two
}
=
ActivityBuilder
.
insert
(%{
"type"
=>
"Create"
,
"context"
=>
"2hu"
})
{
:ok
,
_activity_three
}
=
ActivityBuilder
.
insert
(%{
"type"
=>
"Create"
,
"context"
=>
"3hu"
})
{
:ok
,
_activity_four
}
=
ActivityBuilder
.
insert
(%{
"type"
=>
"Announce"
,
"context"
=>
"2hu"
})
activity_five
=
insert
(
:note_activity
)
user
=
insert
(
:user
)
activities
=
ActivityPub
.
fetch_activities_for_context
(
"2hu"
)
{
:ok
,
user
}
=
User
.
block
(
user
,
%{
ap_id:
activity_five
.
data
[
"actor"
]}
)
activities
=
ActivityPub
.
fetch_activities_for_context
(
"2hu"
,
%{
"blocking_user"
=>
user
})
assert
activities
==
[
activity_two
,
activity
]
end
end
test
"doesn't return blocked activities"
do
activity_one
=
insert
(
:note_activity
)
activity_two
=
insert
(
:note_activity
)
user
=
insert
(
:user
)
{
:ok
,
user
}
=
User
.
block
(
user
,
%{
ap_id:
activity_one
.
data
[
"actor"
]})
activities
=
ActivityPub
.
fetch_activities
([],
%{
"blocking_user"
=>
user
})
assert
Enum
.
member?
(
activities
,
activity_two
)
refute
Enum
.
member?
(
activities
,
activity_one
)
{
:ok
,
user
}
=
User
.
unblock
(
user
,
%{
ap_id:
activity_one
.
data
[
"actor"
]})
activities
=
ActivityPub
.
fetch_activities
([],
%{
"blocking_user"
=>
user
})
assert
Enum
.
member?
(
activities
,
activity_two
)
assert
Enum
.
member?
(
activities
,
activity_one
)
activities
=
ActivityPub
.
fetch_activities
([],
%{
"blocking_user"
=>
nil
})
assert
Enum
.
member?
(
activities
,
activity_two
)
assert
Enum
.
member?
(
activities
,
activity_one
)
end
describe
"public fetch activities"
do
test
"retrieves public activities"
do
%{
public:
public
}
=
ActivityBuilder
.
public_and_non_public
...
...
test/web/mastodon_api/account_view_test.exs
View file @
fa1f11e8
...
...
@@ -51,12 +51,13 @@ test "represent a relationship" do
other_user
=
insert
(
:user
)
{
:ok
,
user
}
=
User
.
follow
(
user
,
other_user
)
{
:ok
,
user
}
=
User
.
block
(
user
,
other_user
)
expected
=
%{
id:
other_user
.
id
,
following:
true
,
followed_by:
false
,
blocking:
fals
e
,
blocking:
tru
e
,
muting:
false
,
requested:
false
,
domain_blocking:
false
...
...
test/web/mastodon_api/mastodon_api_controller_test.exs
View file @
fa1f11e8
...
...
@@ -291,11 +291,43 @@ test "following / unfollowing a user", %{conn: conn} do
assert
id
==
other_user
.
id
end
test
"
unimplemented block/mute endpoints"
do
test
"
blocking / unblocking a user"
,
%{
conn:
conn
}
do
user
=
insert
(
:user
)
other_user
=
insert
(
:user
)
[
"block"
,
"unblock"
,
"mute"
,
"unmute"
]
conn
=
conn
|>
assign
(
:user
,
user
)
|>
post
(
"/api/v1/accounts/
#{
other_user
.
id
}
/block"
)
assert
%{
"id"
=>
id
,
"blocking"
=>
true
}
=
json_response
(
conn
,
200
)
user
=
Repo
.
get
(
User
,
user
.
id
)
conn
=
build_conn
()
|>
assign
(
:user
,
user
)
|>
post
(
"/api/v1/accounts/
#{
other_user
.
id
}
/unblock"
)
assert
%{
"id"
=>
id
,
"blocking"
=>
false
}
=
json_response
(
conn
,
200
)
end
test
"getting a list of blocks"
,
%{
conn:
conn
}
do
user
=
insert
(
:user
)
other_user
=
insert
(
:user
)
{
:ok
,
user
}
=
User
.
block
(
user
,
other_user
)
conn
=
conn
|>
assign
(
:user
,
user
)
|>
get
(
"/api/v1/blocks"
)
other_user_id
=
other_user
.
id
assert
[%{
"id"
=>
^
other_user_id
}]
=
json_response
(
conn
,
200
)
end
test
"unimplemented mute endpoints"
do
user
=
insert
(
:user
)
other_user
=
insert
(
:user
)
[
"mute"
,
"unmute"
]
|>
Enum
.
each
(
fn
(
endpoint
)
->
conn
=
build_conn
()
|>
assign
(
:user
,
user
)
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new 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