Commit cd6da360 authored by Sachin Joshi's avatar Sachin Joshi

Merge branch 'develop' into bugfix/web-notification-special-char

parents 963d5774 77690b9d
......@@ -3,7 +3,6 @@
/db
/deps
/*.ez
/uploads
/test/uploads
/.elixir_ls
/test/fixtures/test_tmp.txt
......
......@@ -16,11 +16,14 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Configuration: `link_name` option
- Configuration: `fetch_initial_posts` option
- Configuration: `notify_email` option
- Pleroma API: User subscribtions
- Configuration: Media proxy `whitelist` option
- Pleroma API: User subscriptions
- Pleroma API: Healthcheck endpoint
- Admin API: Endpoints for listing/revoking invite tokens
- Admin API: Endpoints for making users follow/unfollow each other
- Mastodon API: [Scheduled statuses](https://docs.joinmastodon.org/api/rest/scheduled-statuses/)
- Mastodon API: `/api/v1/notifications/destroy_multiple` (glitch-soc extension)
- Mastodon API: `/api/v1/pleroma/accounts/:id/favourites` (API extension)
- Mastodon API: [Reports](https://docs.joinmastodon.org/api/rest/reports/)
- ActivityPub C2S: OAuth endpoints
- Metadata RelMe provider
......@@ -38,11 +41,14 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Configuration: Dedupe enabled by default
- Configuration: Added `extra_cookie_attrs` for setting non-standard cookie attributes. Defaults to ["SameSite=Lax"] so that remote follows work.
- Pleroma API: Support for emoji tags in `/api/pleroma/emoji` resulting in a breaking API change
- Timelines: Messages involving people you have blocked will be excluded from the timeline in all cases instead of just repeats.
- Mastodon API: Support for `exclude_types`, `limit` and `min_id` in `/api/v1/notifications`
- Mastodon API: Add `languages` and `registrations` to `/api/v1/instance`
- Mastodon API: Provide plaintext versions of cw/content in the Status entity
- Mastodon API: Add `pleroma.conversation_id` field to the Status entity
- Mastodon API: Add `pleroma.tags`, `pleroma.relationship{}`, `pleroma.is_moderator`, `pleroma.is_admin`, `pleroma.confirmation_pending` fields to the User entity
- Mastodon API: Add `pleroma.conversation_id`, `pleroma.in_reply_to_account_acct` fields to the Status entity
- Mastodon API: Add `pleroma.tags`, `pleroma.relationship{}`, `pleroma.is_moderator`, `pleroma.is_admin`, `pleroma.confirmation_pending`, `pleroma.hide_followers`, `pleroma.hide_follows`, `pleroma.hide_favorites` fields to the User entity
- Mastodon API: Add `pleroma.show_role`, `pleroma.no_rich_text` fields to the Source subentity
- Mastodon API: Add support for updating `no_rich_text`, `hide_followers`, `hide_follows`, `hide_favorites`, `show_role` in `PATCH /api/v1/update_credentials`
- Mastodon API: Add `pleroma.is_seen` to the Notification entity
- Mastodon API: Add `pleroma.local` to the Status entity
- Mastodon API: Add `preview` parameter to `POST /api/v1/statuses`
......@@ -52,6 +58,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Deps: Updated Cowboy to 2.6
- Deps: Updated Ecto to 3.0.7
- Don't ship finmoji by default, they can be installed as an emoji pack
- Mastodon API: Added support max_id & since_id for bookmark timeline endpoints.
### Fixed
- Followers counter not being updated when a follower is blocked
......@@ -66,16 +73,20 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Federation: Cope with missing or explicitly nulled address lists
- Federation: Explicitly ensure activities addressed to `as:Public` become addressed to the followers collection
- Federation: Better cope with actors which do not declare a followers collection and use `as:Public` with these semantics
- Federation: Follow requests from remote users who have been blocked will be automatically rejected if appropriate
- MediaProxy: Parse name from content disposition headers even for non-whitelisted types
- MediaProxy: S3 link encoding
- Rich Media: Reject any data which cannot be explicitly encoded into JSON
- Pleroma API: Importing follows from Mastodon 2.8+
- Twitter API: Exposing default scope, `no_rich_text` of the user to anyone
- Twitter API: Returning the `role` object in user entity despite `show_role = false`
- Mastodon API: `/api/v1/favourites` serving only public activities
- Mastodon API: Reblogs having `in_reply_to_id` - `null` even when they are replies
- Mastodon API: Streaming API broadcasting wrong activity id
- Mastodon API: 500 errors when requesting a card for a private conversation
- Mastodon API: Handling of `reblogs` in `/api/v1/accounts/:id/follow`
- Mastodon API: Correct `reblogged`, `favourited`, and `bookmarked` values in the reblog status JSON
- Mastodon API: Exposing default scope of the user to anyone
## [0.9.9999] - 2019-04-05
### Security
......
......@@ -221,7 +221,8 @@ config :pleroma, :instance,
allowed_post_formats: [
"text/plain",
"text/html",
"text/markdown"
"text/markdown",
"text/bbcode"
],
mrf_transparency: true,
autofollowed_nicknames: [],
......@@ -230,7 +231,8 @@ config :pleroma, :instance,
welcome_user_nickname: nil,
welcome_message: nil,
max_report_comment_size: 1000,
safe_dm_mentions: false
safe_dm_mentions: false,
healthcheck: false
config :pleroma, :markup,
# XXX - unfortunately, inline images must be enabled by default right now, because
......@@ -325,7 +327,8 @@ config :pleroma, :media_proxy,
follow_redirect: true,
pool: :media
]
]
],
whitelist: []
config :pleroma, :chat, enabled: true
......
......@@ -20,6 +20,7 @@ Has these additional fields under the `pleroma` object:
- `local`: true if the post was made on the local instance.
- `conversation_id`: the ID of the conversation the status is associated with (if any)
- `in_reply_to_account_acct`: the `acct` property of User entity for replied user (if any)
- `content`: a map consisting of alternate representations of the `content` property with the key being it's mimetype. Currently the only alternate representation supported is `text/plain`
- `spoiler_text`: a map consisting of alternate representations of the `spoiler_text` property with the key being it's mimetype. Currently the only alternate representation supported is `text/plain`
......@@ -37,9 +38,18 @@ Has these additional fields under the `pleroma` object:
- `tags`: Lists an array of tags for the user
- `relationship{}`: Includes fields as documented for Mastodon API https://docs.joinmastodon.org/api/entities/#relationship
- `is_moderator`: boolean, true if user is a moderator
- `is_admin`: boolean, true if user is an admin
- `is_moderator`: boolean, nullable, true if user is a moderator
- `is_admin`: boolean, nullable, true if user is an admin
- `confirmation_pending`: boolean, true if a new user account is waiting on email confirmation to be activated
- `hide_followers`: boolean, true when the user has follower hiding enabled
- `hide_follows`: boolean, true when the user has follow hiding enabled
### Source
Has these additional fields under the `pleroma` object:
- `show_role`: boolean, nullable, true when the user wants his role (e.g admin, moderator) to be shown
- `no_rich_text` - boolean, nullable, true when html tags are stripped from all statuses requested from the API
## Account Search
......@@ -59,3 +69,14 @@ Additional parameters can be added to the JSON body/Form data:
- `preview`: boolean, if set to `true` the post won't be actually posted, but the status entitiy would still be rendered back. This could be useful for previewing rich text/custom emoji, for example.
- `content_type`: string, contain the MIME type of the status, it is transformed into HTML by the backend. You can get the list of the supported MIME types with the nodeinfo endpoint.
## PATCH `/api/v1/update_credentials`
Additional parameters can be added to the JSON body/Form data:
- `no_rich_text` - if true, html tags are stripped from all statuses requested from the API
- `hide_followers` - if true, user's followers will be hidden
- `hide_follows` - if true, user's follows will be hidden
- `hide_favorites` - if true, user's favorites timeline will be hidden
- `show_role` - if true, user's role (e.g admin, moderator) will be exposed to anyone in the API
- `default_scope` - the scope returned under `privacy` key in Source subentity
......@@ -77,7 +77,7 @@ Request parameters can be passed via [query strings](https://en.wikipedia.org/wi
* `token`: invite token required when the registrations aren't public.
* Response: JSON. Returns a user object on success, otherwise returns `{"error": "error_msg"}`
* Example response:
```
```json
{
"background_image": null,
"cover_photo": "https://pleroma.soykaf.com/images/banner.png",
......@@ -187,6 +187,62 @@ See [Admin-API](Admin-API.md)
}
```
## `/api/v1/pleroma/accounts/:id/favourites`
### Returns favorites timeline of any user
* Method `GET`
* Authentication: not required
* Params:
* `id`: the id of the account for whom to return results
* `limit`: optional, the number of records to retrieve
* `since_id`: optional, returns results that are more recent than the specified id
* `max_id`: optional, returns results that are older than the specified id
* Response: JSON, returns a list of Mastodon Status entities on success, otherwise returns `{"error": "error_msg"}`
* Example response:
```json
[
{
"account": {
"id": "9hptFmUF3ztxYh3Svg",
"url": "https://pleroma.example.org/users/nick2",
"username": "nick2",
...
},
"application": {"name": "Web", "website": null},
"bookmarked": false,
"card": null,
"content": "This is :moominmamma: note 0",
"created_at": "2019-04-15T15:42:15.000Z",
"emojis": [],
"favourited": false,
"favourites_count": 1,
"id": "9hptFmVJ02khbzYJaS",
"in_reply_to_account_id": null,
"in_reply_to_id": null,
"language": null,
"media_attachments": [],
"mentions": [],
"muted": false,
"pinned": false,
"pleroma": {
"content": {"text/plain": "This is :moominmamma: note 0"},
"conversation_id": 13679,
"local": true,
"spoiler_text": {"text/plain": "2hu"}
},
"reblog": null,
"reblogged": false,
"reblogs_count": 0,
"replies_count": 0,
"sensitive": false,
"spoiler_text": "2hu",
"tags": [{"name": "2hu", "url": "/tag/2hu"}],
"uri": "https://pleroma.example.org/objects/198ed2a1-7912-4482-b559-244a0369e984",
"url": "https://pleroma.example.org/notice/9hptFmVJ02khbzYJaS",
"visibility": "public"
}
]
```
## `/api/pleroma/notification_settings`
### Updates user notification settings
* Method `PUT`
......@@ -197,3 +253,20 @@ See [Admin-API](Admin-API.md)
* `remote`: BOOLEAN field, receives notifications from people on remote instances
* `local`: BOOLEAN field, receives notifications from people on the local instance
* Response: JSON. Returns `{"status": "success"}` if the update was successful, otherwise returns `{"error": "error_msg"}`
## `/api/pleroma/healthcheck`
### Healthcheck endpoint with additional system data.
* Method `GET`
* Authentication: not required
* Params: none
* Response: JSON, statuses (200 - healthy, 503 unhealthy).
* Example response:
```json
{
"pool_size": 0, # database connection pool
"active": 0, # active processes
"idle": 0, # idle processes
"memory_used": 0.00, # Memory used
"healthy": true # Instance state
}
```
......@@ -103,6 +103,7 @@ config :pleroma, Pleroma.Emails.Mailer,
* `welcome_user_nickname`: The nickname of the local user that sends the welcome message.
* `max_report_comment_size`: The maximum size of the report comment (Default: `1000`)
* `safe_dm_mentions`: If set to true, only mentions at the beginning of a post will be used to address people in direct messages. This is to prevent accidental mentioning of people when talking about them (e.g. "@friend hey i really don't like @enemy"). (Default: `false`)
* `healthcheck`: if set to true, system data will be shown on ``/api/pleroma/healthcheck``.
## :logger
* `backends`: `:console` is used to send logs to stdout, `{ExSyslogger, :ex_syslogger}` to log to syslog, and `Quack.Logger` to log to Slack
......@@ -204,6 +205,7 @@ This section is used to configure Pleroma-FE, unless ``:managed_config`` in ``:i
* `enabled`: Enables proxying of remote media to the instance’s proxy
* `base_url`: The base URL to access a user-uploaded file. Useful when you want to proxy the media files via another host/CDN fronts.
* `proxy_opts`: All options defined in `Pleroma.ReverseProxy` documentation, defaults to `[max_body_length: (25*1_048_576)]`.
* `whitelist`: List of domains to bypass the mediaproxy
## :gopher
* `enabled`: Enables the gopher interface
......@@ -486,3 +488,8 @@ config :ueberauth, Ueberauth,
microsoft: {Ueberauth.Strategy.Microsoft, [callback_params: []]}
]
```
## :emoji
* `shortcode_globs`: Location of custom emoji files. `*` can be used as a wildcard. Example `["/emoji/custom/**/*.png"]`
* `groups`: Emojis are ordered in groups (tags). This is an array of key-value pairs where the key is the groupname and the value the location or array of locations. `*` can be used as a wildcard. Example `[Custom: ["/emoji/*.png", "/emoji/custom/*.png"]]`
* `default_manifest`: Location of the JSON-manifest. This manifest contains information about the emoji-packs you can download. Currently only one manifest can be added (no arrays).
......@@ -28,6 +28,11 @@ foo, /emoji/custom/foo.png
The files should be PNG (APNG is okay with `.png` for `image/png` Content-type) and under 50kb for compatibility with mastodon.
Default file extentions and locations for emojis are set in `config.exs`. To use different locations or file-extentions, add the `shortcode_globs` to your secrets file (`prod.secret.exs` or `dev.secret.exs`) and edit it. Note that not all fediverse-software will show emojis with other file extentions:
```elixir
config :pleroma, :emoji, shortcode_globs: ["/emoji/custom/**/*.png", "/emoji/custom/**/*.gif"]
```
## Emoji tags (groups)
Default tags are set in `config.exs`. To set your own tags, copy the structure to your secrets file (`prod.secret.exs` or `dev.secret.exs`) and edit it.
......
defmodule Pleroma.Healthcheck do
@moduledoc """
Module collects metrics about app and assign healthy status.
"""
alias Pleroma.Healthcheck
alias Pleroma.Repo
defstruct pool_size: 0,
active: 0,
idle: 0,
memory_used: 0,
healthy: true
@type t :: %__MODULE__{
pool_size: non_neg_integer(),
active: non_neg_integer(),
idle: non_neg_integer(),
memory_used: number(),
healthy: boolean()
}
@spec system_info() :: t()
def system_info do
%Healthcheck{
memory_used: Float.round(:erlang.memory(:total) / 1024 / 1024, 2)
}
|> assign_db_info()
|> check_health()
end
defp assign_db_info(healthcheck) do
database = Application.get_env(:pleroma, Repo)[:database]
query =
"select state, count(pid) from pg_stat_activity where datname = '#{database}' group by state;"
result = Repo.query!(query)
pool_size = Application.get_env(:pleroma, Repo)[:pool_size]
db_info =
Enum.reduce(result.rows, %{active: 0, idle: 0}, fn [state, cnt], states ->
if state == "active" do
Map.put(states, :active, states.active + cnt)
else
Map.put(states, :idle, states.idle + cnt)
end
end)
|> Map.put(:pool_size, pool_size)
Map.merge(healthcheck, db_info)
end
@spec check_health(Healthcheck.t()) :: Healthcheck.t()
def check_health(%{pool_size: pool_size, active: active} = check)
when active >= pool_size do
%{check | healthy: false}
end
def check_health(check), do: check
end
......@@ -11,7 +11,7 @@ defmodule Mix.Tasks.Pleroma.Emoji do
## ls-packs
mix pleroma.emoji ls-packs [OPTION...]
mix pleroma.emoji ls-packs [OPTION...]
Lists the emoji packs and metadata specified in the manifest.
......@@ -23,10 +23,10 @@ defmodule Mix.Tasks.Pleroma.Emoji do
## get-packs
mix pleroma.emoji get-packs [OPTION...] PACKS
mix pleroma.emoji get-packs [OPTION...] PACKS
Fetches, verifies and installs the specified PACKS from the
manifest into the `STATIC-DIR/emoji/PACK-NAME
manifest into the `STATIC-DIR/emoji/PACK-NAME`
### Options
......@@ -34,7 +34,7 @@ defmodule Mix.Tasks.Pleroma.Emoji do
## gen-pack
mix pleroma.emoji gen-pack PACK-URL
mix pleroma.emoji gen-pack PACK-URL
Creates a new manifest entry and a file list from the specified
remote pack file. Currently, only .zip archives are recognized
......
......@@ -162,7 +162,7 @@ defmodule Mix.Tasks.Pleroma.User do
def run(["rm", nickname]) do
Common.start_pleroma()
with %User{local: true} = user <- User.get_by_nickname(nickname) do
with %User{local: true} = user <- User.get_cached_by_nickname(nickname) do
User.delete(user)
Mix.shell().info("User #{nickname} deleted.")
else
......@@ -174,7 +174,7 @@ defmodule Mix.Tasks.Pleroma.User do
def run(["toggle_activated", nickname]) do
Common.start_pleroma()
with %User{} = user <- User.get_by_nickname(nickname) do
with %User{} = user <- User.get_cached_by_nickname(nickname) do
{:ok, user} = User.deactivate(user, !user.info.deactivated)
Mix.shell().info(
......@@ -189,7 +189,7 @@ defmodule Mix.Tasks.Pleroma.User do
def run(["reset_password", nickname]) do
Common.start_pleroma()
with %User{local: true} = user <- User.get_by_nickname(nickname),
with %User{local: true} = user <- User.get_cached_by_nickname(nickname),
{:ok, token} <- Pleroma.PasswordResetToken.create_token(user) do
Mix.shell().info("Generated password reset token for #{user.nickname}")
......@@ -211,14 +211,14 @@ defmodule Mix.Tasks.Pleroma.User do
def run(["unsubscribe", nickname]) do
Common.start_pleroma()
with %User{} = user <- User.get_by_nickname(nickname) do
with %User{} = user <- User.get_cached_by_nickname(nickname) do
Mix.shell().info("Deactivating #{user.nickname}")
User.deactivate(user)
{:ok, friends} = User.get_friends(user)
Enum.each(friends, fn friend ->
user = User.get_by_id(user.id)
user = User.get_cached_by_id(user.id)
Mix.shell().info("Unsubscribing #{friend.nickname} from #{user.nickname}")
User.unfollow(user, friend)
......@@ -226,7 +226,7 @@ defmodule Mix.Tasks.Pleroma.User do
:timer.sleep(500)
user = User.get_by_id(user.id)
user = User.get_cached_by_id(user.id)
if Enum.empty?(user.following) do
Mix.shell().info("Successfully unsubscribed all followers from #{user.nickname}")
......@@ -250,7 +250,7 @@ defmodule Mix.Tasks.Pleroma.User do
]
)
with %User{local: true} = user <- User.get_by_nickname(nickname) do
with %User{local: true} = user <- User.get_cached_by_nickname(nickname) do
user =
case Keyword.get(options, :moderator) do
nil -> user
......@@ -277,7 +277,7 @@ defmodule Mix.Tasks.Pleroma.User do
def run(["tag", nickname | tags]) do
Common.start_pleroma()
with %User{} = user <- User.get_by_nickname(nickname) do
with %User{} = user <- User.get_cached_by_nickname(nickname) do
user = user |> User.tag(tags)
Mix.shell().info("Tags of #{user.nickname}: #{inspect(tags)}")
......@@ -290,7 +290,7 @@ defmodule Mix.Tasks.Pleroma.User do
def run(["untag", nickname | tags]) do
Common.start_pleroma()
with %User{} = user <- User.get_by_nickname(nickname) do
with %User{} = user <- User.get_cached_by_nickname(nickname) do
user = user |> User.untag(tags)
Mix.shell().info("Tags of #{user.nickname}: #{inspect(tags)}")
......@@ -379,7 +379,7 @@ defmodule Mix.Tasks.Pleroma.User do
def run(["delete_activities", nickname]) do
Common.start_pleroma()
with %User{local: true} = user <- User.get_by_nickname(nickname) do
with %User{local: true} = user <- User.get_cached_by_nickname(nickname) do
User.delete_user_activities(user)
Mix.shell().info("User #{nickname} statuses deleted.")
else
......
......@@ -39,7 +39,7 @@ defmodule Pleroma.PasswordResetToken do
def reset_password(token, data) do
with %{used: false} = token <- Repo.get_by(PasswordResetToken, %{token: token}),
%User{} = user <- User.get_by_id(token.user_id),
%User{} = user <- User.get_cached_by_id(token.user_id),
{:ok, _user} <- User.reset_password(user, data),
{:ok, token} <- Repo.update(used_changeset(token)) do
{:ok, token}
......
defmodule Pleroma.Bookmark do
use Ecto.Schema
import Ecto.Changeset
import Ecto.Query
alias Pleroma.Activity
alias Pleroma.Bookmark
alias Pleroma.FlakeId
alias Pleroma.Repo
alias Pleroma.User
@type t :: %__MODULE__{}
schema "bookmarks" do
belongs_to(:user, User, type: FlakeId)
belongs_to(:activity, Activity, type: FlakeId)
timestamps()
end
@spec create(FlakeId.t(), FlakeId.t()) :: {:ok, Bookmark.t()} | {:error, Changeset.t()}
def create(user_id, activity_id) do
attrs = %{
user_id: user_id,
activity_id: activity_id
}
%Bookmark{}
|> cast(attrs, [:user_id, :activity_id])
|> validate_required([:user_id, :activity_id])
|> unique_constraint(:activity_id, name: :bookmarks_user_id_activity_id_index)
|> Repo.insert()
end
@spec for_user_query(FlakeId.t()) :: Ecto.Query.t()
def for_user_query(user_id) do
Bookmark
|> where(user_id: ^user_id)
|> join(:inner, [b], activity in assoc(b, :activity))
|> preload([b, a], activity: a)
end
def get(user_id, activity_id) do
Bookmark
|> where(user_id: ^user_id)
|> where(activity_id: ^activity_id)
|> Repo.one()
end
@spec destroy(FlakeId.t(), FlakeId.t()) :: {:ok, Bookmark.t()} | {:error, Changeset.t()}
def destroy(user_id, activity_id) do
from(b in Bookmark,
where: b.user_id == ^user_id,
where: b.activity_id == ^activity_id
)
|> Repo.one()
|> Repo.delete()
end
end
......@@ -76,7 +76,7 @@ defmodule Pleroma.Gopher.Server.ProtocolHandler do
|> Enum.map(fn activity ->
user = User.get_cached_by_ap_id(activity.data["actor"])
object = Object.normalize(activity.data["object"])
object = Object.normalize(activity)
like_count = object["like_count"] || 0
announcement_count = object["announcement_count"] || 0
......
......@@ -106,7 +106,14 @@ defmodule Pleroma.HTML.Scrubber.TwitterText do
# links
Meta.allow_tag_with_uri_attributes("a", ["href", "data-user", "data-tag"], @valid_schemes)
Meta.allow_tag_with_these_attributes("a", ["name", "title", "class"])
Meta.allow_tag_with_this_attribute_values("a", "class", [
"hashtag",
"u-url",
"mention",
"u-url mention",
"mention u-url"
])
Meta.allow_tag_with_this_attribute_values("a", "rel", [
"tag",
......@@ -115,12 +122,15 @@ defmodule Pleroma.HTML.Scrubber.TwitterText do
"noreferrer"
])
Meta.allow_tag_with_these_attributes("a", ["name", "title"])
# paragraphs and linebreaks
Meta.allow_tag_with_these_attributes("br", [])
Meta.allow_tag_with_these_attributes("p", [])
# microformats
Meta.allow_tag_with_these_attributes("span", ["class"])
Meta.allow_tag_with_this_attribute_values("span", "class", ["h-card"])
Meta.allow_tag_with_these_attributes("span", [])
# allow inline images for custom emoji
@allow_inline_images Keyword.get(@markup, :allow_inline_images)
......@@ -155,7 +165,14 @@ defmodule Pleroma.HTML.Scrubber.Default do
Meta.strip_comments()
Meta.allow_tag_with_uri_attributes("a", ["href", "data-user", "data-tag"], @valid_schemes)
Meta.allow_tag_with_these_attributes("a", ["name", "title", "class"])
Meta.allow_tag_with_this_attribute_values("a", "class", [
"hashtag",
"u-url",
"mention",
"u-url mention",
"mention u-url"
])
Meta.allow_tag_with_this_attribute_values("a", "rel", [
"tag",
......@@ -164,6 +181,8 @@ defmodule Pleroma.HTML.Scrubber.Default do
"noreferrer"
])
Meta.allow_tag_with_these_attributes("a", ["name", "title"])
Meta.allow_tag_with_these_attributes("abbr", ["title"])
Meta.allow_tag_with_these_attributes("b", [])
......@@ -177,11 +196,13 @@ defmodule Pleroma.HTML.Scrubber.Default do
Meta.allow_tag_with_these_attributes("ol", [])
Meta.allow_tag_with_these_attributes("p", [])
Meta.allow_tag_with_these_attributes("pre", [])
Meta.allow_tag_with_these_attributes("span", ["class"])
Meta.allow_tag_with_these_attributes("strong", [])
Meta.allow_tag_with_these_attributes("u", [])
Meta.allow_tag_with_these_attributes("ul", [])
Meta.allow_tag_with_this_attribute_values("span", "class", ["h-card"])
Meta.allow_tag_with_these_attributes("span", [])
@allow_inline_images Keyword.get(@markup, :allow_inline_images)
if @allow_inline_images do
......
......@@ -80,7 +80,7 @@ defmodule Pleroma.List do
# Get lists to which the account belongs.
def get_lists_account_belongs(%User{} = owner, account_id) do
user = User.get_by_id(account_id)
user = User.get_cached_by_id(account_id)
query =
from(
......
......@@ -196,7 +196,7 @@ defmodule Pleroma.Notification do
def skip?(:follows, activity, %{info: %{notification_settings: %{"follows" => false}}} = user) do
actor = activity.data["actor"]
followed = User.get_by_ap_id(actor)
followed = User.get_cached_by_ap_id(actor)
User.following?(user, followed)
end
......
......@@ -39,7 +39,7 @@ defmodule Pleroma.Object.Fetcher do
Logger.info("Couldn't get object via AP, trying out OStatus fetching...")
case OStatus.fetch_activity_from_url(id) do
{:ok, [activity | _]} -> {:ok, Object.normalize(activity.data["object"], false)}
{:ok, [activity | _]} -> {:ok, Object.normalize(activity, false)}
e -> e
end
end
......
......@@ -10,6 +10,7 @@ defmodule Pleroma.User do
alias Comeonin.Pbkdf2
alias Pleroma.Activity
alias Pleroma.Bookmark
alias Pleroma.Formatter
alias Pleroma.Notification
alias Pleroma.Object
......@@ -53,8 +54,8 @@ defmodule Pleroma.User do
field(:search_rank, :float, virtual: true)
field(:search_type, :integer, virtual: true)
field(:tags, {:array, :string}, default: [])
field(:bookmarks, {:array, :string}, default: [])
field(:last_refreshed_at, :naive_datetime_usec)
has_many(:bookmarks, Bookmark)
has_many(:notifications, Notification)
has_many(:registrations, Registration)
embeds_one(:info, Pleroma.User.Info)
......@@ -269,6 +270,7 @@ defmodule Pleroma.User do
def register(%Ecto.Changeset{} = changeset) do
with {:ok, user} <- Repo.insert(changeset),
{:ok, user} <- autofollow_users(user),
{:ok, user} <- set_cache(user),
{:ok, _} <- Pleroma.User.WelcomeMessage.post_welcome_message_to_user(user),
{:ok, _} <- try_send_confirmation_email(user) do
{:ok, user}
......@@ -453,10 +455,13 @@ defmodule Pleroma.User do
name = List.last(String.split(ap_id, "/"))
nickname = "#{name}@#{domain}"
get_by_nickname(nickname)
get_cached_by_nickname(nickname)
end
def set_cache(user) do
def set_cache({:ok, user}), do: set_cache(user)
def set_cache({:error, err}), do: {:error, err}
def set_cache(%User{} = user) do
Cachex.put(:user_cache, "ap_id:#{user.ap_id}", user)
Cachex.put(:user_cache, "nickname:#{user.nickname}", user)
Cachex.put(:user_cache, "user_info:#{user.id}", user_info(user))
......@@ -544,6 +549,7 @@ defmodule Pleroma.User do
with [_nick, _domain] <- String.split(nickname, "@"),
{:ok, user} <- fetch_by_nickname(nickname) do
if Pleroma.Config.get([:fetch_initial_posts, :enabled]) do
# TODO turn into job
{:ok, _} = Task.start(__MODULE__, :fetch_initial_posts, [user])
end
......@@ -1002,7 +1008,7 @@ defmodule Pleroma.User do
# helper to handle the block given only an actor's AP id
def block(blocker, %{ap_id: ap_id}) do
block(blocker, User.get_by_ap_id(ap_id))
block(blocker, get_cached_by_ap_id(ap_id))
end
def unblock(blocker, %{ap_id: ap_id}) do
......@@ -1032,7 +1038,7 @@ defmodule Pleroma.User do
end