Commit 00f9b53f authored by feld's avatar feld

Merge branch 'refactor/notification_settings' into 'develop'

Refactor notification settings

See merge request pleroma/pleroma!2602
parents 0fe36b31 34d1d3e9
......@@ -25,6 +25,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Mastodon API: Added `pleroma.metadata.fields_limits` to /api/v1/instance
- Mastodon API: On deletion, returns the original post text.
- Mastodon API: Add `pleroma.unread_count` to the Marker entity.
- **Breaking:** Notification Settings API for suppressing notifications
has been simplified down to `block_from_strangers`.
- **Breaking:** Notification Settings API option for hiding push notification
contents has been renamed to `hide_notification_contents`
</details>
<details>
......
......@@ -287,11 +287,8 @@ See [Admin-API](admin_api.md)
* Method `PUT`
* Authentication: required
* Params:
* `followers`: BOOLEAN field, receives notifications from followers
* `follows`: BOOLEAN field, receives notifications from people the user follows
* `remote`: BOOLEAN field, receives notifications from people on remote instances
* `local`: BOOLEAN field, receives notifications from people on the local instance
* `privacy_option`: BOOLEAN field. When set to true, it removes the contents of a message from the push notification.
* `block_from_strangers`: BOOLEAN field, blocks notifications from accounts you do not follow
* `hide_notification_contents`: BOOLEAN field. When set to true, it removes the contents of a message from the push notification.
* Response: JSON. Returns `{"status": "success"}` if the update was successful, otherwise returns `{"error": "error_msg"}`
## `/api/pleroma/healthcheck`
......
......@@ -3,8 +3,8 @@ defmodule Mix.Tasks.Pleroma.NotificationSettings do
@moduledoc """
Example:
> mix pleroma.notification_settings --privacy-option=false --nickname-users="parallel588" # set false only for parallel588 user
> mix pleroma.notification_settings --privacy-option=true # set true for all users
> mix pleroma.notification_settings --hide-notification-contents=false --nickname-users="parallel588" # set false only for parallel588 user
> mix pleroma.notification_settings --hide-notification-contents=true # set true for all users
"""
......@@ -19,16 +19,16 @@ def run(args) do
OptionParser.parse(
args,
strict: [
privacy_option: :boolean,
hide_notification_contents: :boolean,
email_users: :string,
nickname_users: :string
]
)
privacy_option = Keyword.get(options, :privacy_option)
hide_notification_contents = Keyword.get(options, :hide_notification_contents)
if not is_nil(privacy_option) do
privacy_option
if not is_nil(hide_notification_contents) do
hide_notification_contents
|> build_query(options)
|> Pleroma.Repo.update_all([])
end
......@@ -36,15 +36,15 @@ def run(args) do
shell_info("Done")
end
defp build_query(privacy_option, options) do
defp build_query(hide_notification_contents, options) do
query =
from(u in Pleroma.User,
update: [
set: [
notification_settings:
fragment(
"jsonb_set(notification_settings, '{privacy_option}', ?)",
^privacy_option
"jsonb_set(notification_settings, '{hide_notification_contents}', ?)",
^hide_notification_contents
)
]
]
......
......@@ -571,10 +571,7 @@ def skip?(%Activity{} = activity, %User{} = user) do
[
:self,
:invisible,
:followers,
:follows,
:non_followers,
:non_follows,
:block_from_strangers,
:recently_followed,
:filtered
]
......@@ -595,45 +592,15 @@ def skip?(:invisible, %Activity{} = activity, _) do
end
def skip?(
:followers,
:block_from_strangers,
%Activity{} = activity,
%User{notification_settings: %{followers: false}} = user
) do
actor = activity.data["actor"]
follower = User.get_cached_by_ap_id(actor)
User.following?(follower, user)
end
def skip?(
:non_followers,
%Activity{} = activity,
%User{notification_settings: %{non_followers: false}} = user
%User{notification_settings: %{block_from_strangers: true}} = user
) do
actor = activity.data["actor"]
follower = User.get_cached_by_ap_id(actor)
!User.following?(follower, user)
end
def skip?(
:follows,
%Activity{} = activity,
%User{notification_settings: %{follows: false}} = user
) do
actor = activity.data["actor"]
followed = User.get_cached_by_ap_id(actor)
User.following?(user, followed)
end
def skip?(
:non_follows,
%Activity{} = activity,
%User{notification_settings: %{non_follows: false}} = user
) do
actor = activity.data["actor"]
followed = User.get_cached_by_ap_id(actor)
!User.following?(user, followed)
end
# To do: consider defining recency in hours and checking FollowingRelationship with a single SQL
def skip?(:recently_followed, %Activity{data: %{"type" => "Follow"}} = activity, %User{} = user) do
actor = activity.data["actor"]
......
......@@ -10,21 +10,15 @@ defmodule Pleroma.User.NotificationSetting do
@primary_key false
embedded_schema do
field(:followers, :boolean, default: true)
field(:follows, :boolean, default: true)
field(:non_follows, :boolean, default: true)
field(:non_followers, :boolean, default: true)
field(:privacy_option, :boolean, default: false)
field(:block_from_strangers, :boolean, default: false)
field(:hide_notification_contents, :boolean, default: false)
end
def changeset(schema, params) do
schema
|> cast(prepare_attrs(params), [
:followers,
:follows,
:non_follows,
:non_followers,
:privacy_option
:block_from_strangers,
:hide_notification_contents
])
end
......
......@@ -90,11 +90,8 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Account do
notification_settings: %Schema{
type: :object,
properties: %{
followers: %Schema{type: :boolean},
follows: %Schema{type: :boolean},
non_followers: %Schema{type: :boolean},
non_follows: %Schema{type: :boolean},
privacy_option: %Schema{type: :boolean}
block_from_strangers: %Schema{type: :boolean},
hide_notification_contents: %Schema{type: :boolean}
}
},
relationship: AccountRelationship,
......@@ -182,11 +179,8 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Account do
"unread_conversation_count" => 0,
"tags" => [],
"notification_settings" => %{
"followers" => true,
"follows" => true,
"non_followers" => true,
"non_follows" => true,
"privacy_option" => false
"block_from_strangers" => false,
"hide_notification_contents" => false
},
"relationship" => %{
"blocked_by" => false,
......
......@@ -104,7 +104,7 @@ def build_content(notification, actor, object, mastodon_type \\ nil)
def build_content(
%{
user: %{notification_settings: %{privacy_option: true}}
user: %{notification_settings: %{hide_notification_contents: true}}
} = notification,
_actor,
_object,
......
defmodule Pleroma.Repo.Migrations.RenameNotificationPrivacyOption do
use Ecto.Migration
def up do
execute(
"UPDATE users SET notification_settings = notification_settings - 'privacy_option' || jsonb_build_object('hide_notification_contents', notification_settings->'privacy_option')
where notification_settings ? 'privacy_option'
and local"
)
end
def down do
execute(
"UPDATE users SET notification_settings = notification_settings - 'hide_notification_contents' || jsonb_build_object('privacy_option', notification_settings->'hide_notification_contents')
where notification_settings ? 'hide_notification_contents'
and local"
)
end
end
<!DOCTYPE html><html lang=en><head><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1,user-scalable=no"><title>Pleroma</title><!--server-generated-meta--><link rel=icon type=image/png href=/favicon.png><link href=/static/css/app.77b1644622e3bae24b6b.css rel=stylesheet><link href=/static/fontello.1594374054351.css rel=stylesheet></head><body class=hidden><noscript>To use Pleroma, please enable JavaScript.</noscript><div id=app></div><script type=text/javascript src=/static/js/vendors~app.247dc52c7abe6a0dab87.js></script><script type=text/javascript src=/static/js/app.1e68e208590653dab5aa.js></script></body></html>
\ No newline at end of file
<!DOCTYPE html><html lang=en><head><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1,user-scalable=no"><title>Pleroma</title><!--server-generated-meta--><link rel=icon type=image/png href=/favicon.png><link href=/static/css/app.6dbc7dea4fc148c85860.css rel=stylesheet><link href=/static/fontello.1594823398494.css rel=stylesheet></head><body class=hidden><noscript>To use Pleroma, please enable JavaScript.</noscript><div id=app></div><script type=text/javascript src=/static/js/vendors~app.9e24ed238da5a8538f50.js></script><script type=text/javascript src=/static/js/app.31bba9f1e242ff273dcb.js></script></body></html>
\ No newline at end of file
......@@ -243,4 +243,4 @@
cursor: pointer;
}
/*# sourceMappingURL=app.77b1644622e3bae24b6b.css.map*/
\ No newline at end of file
/*# sourceMappingURL=app.6dbc7dea4fc148c85860.css.map*/
\ No newline at end of file
@font-face {
font-family: "Icons";
src: url("./font/fontello.1589385935077.eot");
src: url("./font/fontello.1589385935077.eot") format("embedded-opentype"),
url("./font/fontello.1589385935077.woff2") format("woff2"),
url("./font/fontello.1589385935077.woff") format("woff"),
url("./font/fontello.1589385935077.ttf") format("truetype"),
url("./font/fontello.1589385935077.svg") format("svg");
font-weight: normal;
font-style: normal;
}
[class^="icon-"]::before,
[class*=" icon-"]::before {
font-family: "Icons";
font-style: normal;
font-weight: normal;
speak: none;
display: inline-block;
text-decoration: inherit;
width: 1em;
margin-right: .2em;
text-align: center;
font-variant: normal;
text-transform: none;
line-height: 1em;
margin-left: .2em;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.icon-spin4::before { content: "\e834"; }
.icon-cancel::before { content: "\e800"; }
.icon-upload::before { content: "\e801"; }
.icon-spin3::before { content: "\e832"; }
.icon-reply::before { content: "\f112"; }
.icon-star::before { content: "\e802"; }
.icon-star-empty::before { content: "\e803"; }
.icon-retweet::before { content: "\e804"; }
.icon-eye-off::before { content: "\e805"; }
.icon-binoculars::before { content: "\f1e5"; }
.icon-cog::before { content: "\e807"; }
.icon-user-plus::before { content: "\f234"; }
.icon-menu::before { content: "\f0c9"; }
.icon-logout::before { content: "\e808"; }
.icon-down-open::before { content: "\e809"; }
.icon-attach::before { content: "\e80a"; }
.icon-link-ext::before { content: "\f08e"; }
.icon-link-ext-alt::before { content: "\f08f"; }
.icon-picture::before { content: "\e80b"; }
.icon-video::before { content: "\e80c"; }
.icon-right-open::before { content: "\e80d"; }
.icon-left-open::before { content: "\e80e"; }
.icon-up-open::before { content: "\e80f"; }
.icon-comment-empty::before { content: "\f0e5"; }
.icon-mail-alt::before { content: "\f0e0"; }
.icon-lock::before { content: "\e811"; }
.icon-lock-open-alt::before { content: "\f13e"; }
.icon-globe::before { content: "\e812"; }
.icon-brush::before { content: "\e813"; }
.icon-search::before { content: "\e806"; }
.icon-adjust::before { content: "\e816"; }
.icon-thumbs-up-alt::before { content: "\f164"; }
.icon-attention::before { content: "\e814"; }
.icon-plus-squared::before { content: "\f0fe"; }
.icon-plus::before { content: "\e815"; }
.icon-edit::before { content: "\e817"; }
.icon-play-circled::before { content: "\f144"; }
.icon-pencil::before { content: "\e818"; }
.icon-chart-bar::before { content: "\e81b"; }
.icon-smile::before { content: "\f118"; }
.icon-bell-alt::before { content: "\f0f3"; }
.icon-wrench::before { content: "\e81a"; }
.icon-pin::before { content: "\e819"; }
.icon-ellipsis::before { content: "\f141"; }
.icon-bell-ringing-o::before { content: "\e810"; }
.icon-zoom-in::before { content: "\e81c"; }
.icon-gauge::before { content: "\f0e4"; }
.icon-users::before { content: "\e81d"; }
.icon-info-circled::before { content: "\e81f"; }
.icon-home-2::before { content: "\e821"; }
.icon-chat::before { content: "\e81e"; }
.icon-login::before { content: "\e820"; }
.icon-arrow-curved::before { content: "\e822"; }
.icon-link::before { content: "\e823"; }
.icon-share::before { content: "\f1e0"; }
.icon-user::before { content: "\e824"; }
.icon-ok::before { content: "\e827"; }
@font-face {
font-family: "Icons";
src: url("./font/fontello.1594030805019.eot");
src: url("./font/fontello.1594030805019.eot") format("embedded-opentype"),
url("./font/fontello.1594030805019.woff2") format("woff2"),
url("./font/fontello.1594030805019.woff") format("woff"),
url("./font/fontello.1594030805019.ttf") format("truetype"),
url("./font/fontello.1594030805019.svg") format("svg");
font-weight: normal;
font-style: normal;
}
[class^="icon-"]::before,
[class*=" icon-"]::before {
font-family: "Icons";
font-style: normal;
font-weight: normal;
speak: none;
display: inline-block;
text-decoration: inherit;
width: 1em;
margin-right: .2em;
text-align: center;
font-variant: normal;
text-transform: none;
line-height: 1em;
margin-left: .2em;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.icon-spin4::before { content: "\e834"; }
.icon-cancel::before { content: "\e800"; }
.icon-upload::before { content: "\e801"; }
.icon-spin3::before { content: "\e832"; }
.icon-reply::before { content: "\f112"; }
.icon-star::before { content: "\e802"; }
.icon-star-empty::before { content: "\e803"; }
.icon-retweet::before { content: "\e804"; }
.icon-eye-off::before { content: "\e805"; }
.icon-binoculars::before { content: "\f1e5"; }
.icon-cog::before { content: "\e807"; }
.icon-user-plus::before { content: "\f234"; }
.icon-menu::before { content: "\f0c9"; }
.icon-logout::before { content: "\e808"; }
.icon-down-open::before { content: "\e809"; }
.icon-attach::before { content: "\e80a"; }
.icon-link-ext::before { content: "\f08e"; }
.icon-link-ext-alt::before { content: "\f08f"; }
.icon-picture::before { content: "\e80b"; }
.icon-video::before { content: "\e80c"; }
.icon-right-open::before { content: "\e80d"; }
.icon-left-open::before { content: "\e80e"; }
.icon-up-open::before { content: "\e80f"; }
.icon-comment-empty::before { content: "\f0e5"; }
.icon-mail-alt::before { content: "\f0e0"; }
.icon-lock::before { content: "\e811"; }
.icon-lock-open-alt::before { content: "\f13e"; }
.icon-globe::before { content: "\e812"; }
.icon-brush::before { content: "\e813"; }
.icon-search::before { content: "\e806"; }
.icon-adjust::before { content: "\e816"; }
.icon-thumbs-up-alt::before { content: "\f164"; }
.icon-attention::before { content: "\e814"; }
.icon-plus-squared::before { content: "\f0fe"; }
.icon-plus::before { content: "\e815"; }
.icon-edit::before { content: "\e817"; }
.icon-play-circled::before { content: "\f144"; }
.icon-pencil::before { content: "\e818"; }
.icon-chart-bar::before { content: "\e81b"; }
.icon-smile::before { content: "\f118"; }
.icon-bell-alt::before { content: "\f0f3"; }
.icon-wrench::before { content: "\e81a"; }
.icon-pin::before { content: "\e819"; }
.icon-ellipsis::before { content: "\f141"; }
.icon-bell-ringing-o::before { content: "\e810"; }
.icon-zoom-in::before { content: "\e81c"; }
.icon-gauge::before { content: "\f0e4"; }
.icon-users::before { content: "\e81d"; }
.icon-info-circled::before { content: "\e81f"; }
.icon-home-2::before { content: "\e821"; }
.icon-chat::before { content: "\e81e"; }
.icon-login::before { content: "\e820"; }
.icon-arrow-curved::before { content: "\e822"; }
.icon-link::before { content: "\e823"; }
.icon-share::before { content: "\f1e0"; }
.icon-user::before { content: "\e824"; }
.icon-ok::before { content: "\e827"; }
.icon-filter::before { content: "\f0b0"; }
.icon-download::before { content: "\e825"; }
.icon-bookmark::before { content: "\e826"; }
.icon-bookmark-empty::before { content: "\f097"; }
@font-face {
font-family: "Icons";
src: url("./font/fontello.1594134783339.eot");
src: url("./font/fontello.1594134783339.eot") format("embedded-opentype"),
url("./font/fontello.1594134783339.woff2") format("woff2"),
url("./font/fontello.1594134783339.woff") format("woff"),
url("./font/fontello.1594134783339.ttf") format("truetype"),
url("./font/fontello.1594134783339.svg") format("svg");
font-weight: normal;
font-style: normal;
}
[class^="icon-"]::before,
[class*=" icon-"]::before {
font-family: "Icons";
font-style: normal;
font-weight: normal;
speak: none;
display: inline-block;
text-decoration: inherit;
width: 1em;
margin-right: .2em;
text-align: center;
font-variant: normal;
text-transform: none;
line-height: 1em;
margin-left: .2em;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.icon-spin4::before { content: "\e834"; }
.icon-cancel::before { content: "\e800"; }
.icon-upload::before { content: "\e801"; }
.icon-spin3::before { content: "\e832"; }
.icon-reply::before { content: "\f112"; }