Merge remote-tracking branch 'origin/develop' into shigusegubu
* origin/develop: Fix bookmarks depending on embeded object and move checking if the status is bookmarked to SQL update pleroma frontend tests: fix up for changed bbcode library output and verify html is properly escaped add support for bbcode mix: add bbcode dependency update Changelog Add mediaproxy whitelist capability Move settings to Source subentity test fixes fixes for tests migration without using old field name unused removing useless transaction migration optimization changelog file update favourites add bookmark display migrate user.bookmarks to separate table bookmarks in separate table activitypub: transmogrifier: send reject follow if following does not succeed Fix leaking private configuration parameters in Mastodon and Twitter APIs, and add new configuration parameters to Mastodon API
This commit is contained in:
commit
10d743e46a
62 changed files with 763 additions and 295 deletions
11
CHANGELOG.md
11
CHANGELOG.md
|
|
@ -16,6 +16,7 @@ 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
|
||||
- Configuration: Media proxy `whitelist` option
|
||||
- Pleroma API: User subscriptions
|
||||
- Pleroma API: Healthcheck endpoint
|
||||
- Admin API: Endpoints for listing/revoking invite tokens
|
||||
|
|
@ -40,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`, `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` fields to the User 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`
|
||||
|
|
@ -54,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
|
||||
|
|
@ -68,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
|
||||
|
|
|
|||
|
|
@ -224,6 +224,7 @@ config :pleroma, :instance,
|
|||
static_dir: "instance/static/",
|
||||
allowed_post_formats: [
|
||||
"text/plain"
|
||||
"text/bbcode"
|
||||
],
|
||||
mrf_transparency: true,
|
||||
autofollowed_nicknames: [],
|
||||
|
|
@ -319,7 +320,8 @@ config :pleroma, :media_proxy,
|
|||
follow_redirect: true,
|
||||
pool: :media
|
||||
]
|
||||
]
|
||||
],
|
||||
whitelist: []
|
||||
|
||||
config :pleroma, :chat, enabled: false
|
||||
|
||||
|
|
|
|||
|
|
@ -38,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
|
||||
|
||||
|
|
@ -60,3 +69,13 @@ 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
|
||||
|
|
|
|||
|
|
@ -205,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
|
||||
|
|
|
|||
60
lib/pleroma/bookmark.ex
Normal file
60
lib/pleroma/bookmark.ex
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
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
|
||||
|
|
@ -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)
|
||||
|
|
@ -1379,22 +1380,6 @@ defmodule Pleroma.User do
|
|||
updated_user
|
||||
end
|
||||
|
||||
def bookmark(%User{} = user, status_id) do
|
||||
bookmarks = Enum.uniq(user.bookmarks ++ [status_id])
|
||||
update_bookmarks(user, bookmarks)
|
||||
end
|
||||
|
||||
def unbookmark(%User{} = user, status_id) do
|
||||
bookmarks = Enum.uniq(user.bookmarks -- [status_id])
|
||||
update_bookmarks(user, bookmarks)
|
||||
end
|
||||
|
||||
def update_bookmarks(%User{} = user, bookmarks) do
|
||||
user
|
||||
|> change(%{bookmarks: bookmarks})
|
||||
|> update_and_set_cache
|
||||
end
|
||||
|
||||
defp normalize_tags(tags) do
|
||||
[tags]
|
||||
|> List.flatten()
|
||||
|
|
|
|||
|
|
@ -227,14 +227,6 @@ defmodule Pleroma.User.Info do
|
|||
cast(info, params, [:confirmation_pending, :confirmation_token])
|
||||
end
|
||||
|
||||
def mastodon_profile_update(info, params) do
|
||||
info
|
||||
|> cast(params, [
|
||||
:locked,
|
||||
:banner
|
||||
])
|
||||
end
|
||||
|
||||
def mastodon_settings_update(info, settings) do
|
||||
params = %{settings: settings}
|
||||
|
||||
|
|
|
|||
|
|
@ -438,20 +438,46 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|
|||
with %User{local: true} = followed <- User.get_cached_by_ap_id(followed),
|
||||
%User{} = follower <- User.get_or_fetch_by_ap_id(follower),
|
||||
{:ok, activity} <- ActivityPub.follow(follower, followed, id, false) do
|
||||
if not User.locked?(followed) do
|
||||
with deny_follow_blocked <- Pleroma.Config.get([:user, :deny_follow_blocked]),
|
||||
{:user_blocked, false} <-
|
||||
{:user_blocked, User.blocks?(followed, follower) && deny_follow_blocked},
|
||||
{:user_locked, false} <- {:user_locked, User.locked?(followed)},
|
||||
{:follow, {:ok, follower}} <- {:follow, User.follow(follower, followed)} do
|
||||
ActivityPub.accept(%{
|
||||
to: [follower.ap_id],
|
||||
actor: followed,
|
||||
object: data,
|
||||
local: true
|
||||
})
|
||||
else
|
||||
{:user_blocked, true} ->
|
||||
{:ok, _} = Utils.update_follow_state(activity, "reject")
|
||||
|
||||
User.follow(follower, followed)
|
||||
ActivityPub.reject(%{
|
||||
to: [follower.ap_id],
|
||||
actor: followed,
|
||||
object: data,
|
||||
local: true
|
||||
})
|
||||
|
||||
{:follow, {:error, _}} ->
|
||||
{:ok, _} = Utils.update_follow_state(activity, "reject")
|
||||
|
||||
ActivityPub.reject(%{
|
||||
to: [follower.ap_id],
|
||||
actor: followed,
|
||||
object: data,
|
||||
local: true
|
||||
})
|
||||
|
||||
{:user_locked, true} ->
|
||||
:noop
|
||||
end
|
||||
|
||||
{:ok, activity}
|
||||
else
|
||||
_e -> :error
|
||||
_e ->
|
||||
:error
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
defmodule Pleroma.Web.CommonAPI do
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.Bookmark
|
||||
alias Pleroma.Formatter
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.ThreadMute
|
||||
|
|
@ -282,6 +283,15 @@ defmodule Pleroma.Web.CommonAPI do
|
|||
end
|
||||
end
|
||||
|
||||
def bookmarked?(user, activity) do
|
||||
with %Bookmark{} <- Bookmark.get(user.id, activity.id) do
|
||||
true
|
||||
else
|
||||
_ ->
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
def report(user, data) do
|
||||
with {:account_id, %{"account_id" => account_id}} <- {:account_id, data},
|
||||
{:account, %User{} = account} <- {:account, User.get_cached_by_id(account_id)},
|
||||
|
|
|
|||
|
|
@ -182,6 +182,18 @@ defmodule Pleroma.Web.CommonAPI.Utils do
|
|||
end).()
|
||||
end
|
||||
|
||||
@doc """
|
||||
Formatting text as BBCode.
|
||||
"""
|
||||
def format_input(text, "text/bbcode", options) do
|
||||
text
|
||||
|> String.replace(~r/\r/, "")
|
||||
|> Formatter.html_escape("text/plain")
|
||||
|> BBCode.to_html()
|
||||
|> (fn {:ok, html} -> html end).()
|
||||
|> Formatter.linkify(options)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Formatting text to html.
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
|
|||
use Pleroma.Web, :controller
|
||||
alias Ecto.Changeset
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.Bookmark
|
||||
alias Pleroma.Config
|
||||
alias Pleroma.Filter
|
||||
alias Pleroma.Notification
|
||||
|
|
@ -35,7 +36,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
|
|||
alias Pleroma.Web.OAuth.Authorization
|
||||
alias Pleroma.Web.OAuth.Token
|
||||
|
||||
import Pleroma.Web.ControllerHelper, only: [oauth_scopes: 2]
|
||||
alias Pleroma.Web.ControllerHelper
|
||||
import Ecto.Query
|
||||
|
||||
require Logger
|
||||
|
|
@ -46,7 +47,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
|
|||
action_fallback(:errors)
|
||||
|
||||
def create_app(conn, params) do
|
||||
scopes = oauth_scopes(params, ["read"])
|
||||
scopes = ControllerHelper.oauth_scopes(params, ["read"])
|
||||
|
||||
app_attrs =
|
||||
params
|
||||
|
|
@ -96,8 +97,12 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
|
|||
end)
|
||||
|
||||
info_params =
|
||||
%{}
|
||||
|> add_if_present(params, "locked", :locked, fn value -> {:ok, value == "true"} end)
|
||||
[:no_rich_text, :locked, :hide_followers, :hide_follows, :hide_favorites, :show_role]
|
||||
|> Enum.reduce(%{}, fn key, acc ->
|
||||
add_if_present(acc, params, to_string(key), key, fn value ->
|
||||
{:ok, ControllerHelper.truthy_param?(value)}
|
||||
end)
|
||||
end)
|
||||
|> add_if_present(params, "header", :banner, fn value ->
|
||||
with %Plug.Upload{} <- value,
|
||||
{:ok, object} <- ActivityPub.upload(value, type: :banner) do
|
||||
|
|
@ -107,7 +112,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
|
|||
end
|
||||
end)
|
||||
|
||||
info_cng = User.Info.mastodon_profile_update(user.info, info_params)
|
||||
info_cng = User.Info.profile_update(user.info, info_params)
|
||||
|
||||
with changeset <- User.update_changeset(user, user_params),
|
||||
changeset <- Ecto.Changeset.put_embed(changeset, :info, info_cng),
|
||||
|
|
@ -279,6 +284,8 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
|
|||
|> ActivityPub.contain_timeline(user)
|
||||
|> Enum.reverse()
|
||||
|
||||
user = Repo.preload(user, bookmarks: :activity)
|
||||
|
||||
conn
|
||||
|> add_link_headers(:home_timeline, activities)
|
||||
|> put_view(StatusView)
|
||||
|
|
@ -297,6 +304,8 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
|
|||
|> ActivityPub.fetch_public_activities()
|
||||
|> Enum.reverse()
|
||||
|
||||
user = Repo.preload(user, bookmarks: :activity)
|
||||
|
||||
conn
|
||||
|> add_link_headers(:public_timeline, activities, false, %{"local" => local_only})
|
||||
|> put_view(StatusView)
|
||||
|
|
@ -304,7 +313,8 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
|
|||
end
|
||||
|
||||
def user_statuses(%{assigns: %{user: reading_user}} = conn, params) do
|
||||
with %User{} = user <- User.get_cached_by_id(params["id"]) do
|
||||
with %User{} = user <- User.get_cached_by_id(params["id"]),
|
||||
reading_user <- Repo.preload(reading_user, :bookmarks) do
|
||||
activities = ActivityPub.fetch_user_activities(user, reading_user, params)
|
||||
|
||||
conn
|
||||
|
|
@ -331,6 +341,8 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
|
|||
|> ActivityPub.fetch_activities_query(params)
|
||||
|> Pagination.fetch_paginated(params)
|
||||
|
||||
user = Repo.preload(user, bookmarks: :activity)
|
||||
|
||||
conn
|
||||
|> add_link_headers(:dm_timeline, activities)
|
||||
|> put_view(StatusView)
|
||||
|
|
@ -340,6 +352,8 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
|
|||
def get_status(%{assigns: %{user: user}} = conn, %{"id" => id}) do
|
||||
with %Activity{} = activity <- Activity.get_by_id_with_object(id),
|
||||
true <- Visibility.visible_for_user?(activity, user) do
|
||||
user = Repo.preload(user, bookmarks: :activity)
|
||||
|
||||
conn
|
||||
|> put_view(StatusView)
|
||||
|> try_render("status.json", %{activity: activity, for: user})
|
||||
|
|
@ -489,6 +503,8 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
|
|||
def reblog_status(%{assigns: %{user: user}} = conn, %{"id" => ap_id_or_id}) do
|
||||
with {:ok, announce, _activity} <- CommonAPI.repeat(ap_id_or_id, user),
|
||||
%Activity{} = announce <- Activity.normalize(announce.data) do
|
||||
user = Repo.preload(user, bookmarks: :activity)
|
||||
|
||||
conn
|
||||
|> put_view(StatusView)
|
||||
|> try_render("status.json", %{activity: announce, for: user, as: :activity})
|
||||
|
|
@ -498,6 +514,8 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
|
|||
def unreblog_status(%{assigns: %{user: user}} = conn, %{"id" => ap_id_or_id}) do
|
||||
with {:ok, _unannounce, %{data: %{"id" => id}}} <- CommonAPI.unrepeat(ap_id_or_id, user),
|
||||
%Activity{} = activity <- Activity.get_create_by_object_ap_id_with_object(id) do
|
||||
user = Repo.preload(user, bookmarks: :activity)
|
||||
|
||||
conn
|
||||
|> put_view(StatusView)
|
||||
|> try_render("status.json", %{activity: activity, for: user, as: :activity})
|
||||
|
|
@ -545,10 +563,11 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
|
|||
|
||||
def bookmark_status(%{assigns: %{user: user}} = conn, %{"id" => id}) do
|
||||
with %Activity{} = activity <- Activity.get_by_id_with_object(id),
|
||||
%Object{} = object <- Object.normalize(activity),
|
||||
%User{} = user <- User.get_cached_by_nickname(user.nickname),
|
||||
true <- Visibility.visible_for_user?(activity, user),
|
||||
{:ok, user} <- User.bookmark(user, object.data["id"]) do
|
||||
{:ok, _bookmark} <- Bookmark.create(user.id, activity.id) do
|
||||
user = Repo.preload(user, bookmarks: :activity)
|
||||
|
||||
conn
|
||||
|> put_view(StatusView)
|
||||
|> try_render("status.json", %{activity: activity, for: user, as: :activity})
|
||||
|
|
@ -557,10 +576,11 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
|
|||
|
||||
def unbookmark_status(%{assigns: %{user: user}} = conn, %{"id" => id}) do
|
||||
with %Activity{} = activity <- Activity.get_by_id_with_object(id),
|
||||
%Object{} = object <- Object.normalize(activity),
|
||||
%User{} = user <- User.get_cached_by_nickname(user.nickname),
|
||||
true <- Visibility.visible_for_user?(activity, user),
|
||||
{:ok, user} <- User.unbookmark(user, object.data["id"]) do
|
||||
{:ok, _bookmark} <- Bookmark.destroy(user.id, activity.id) do
|
||||
user = Repo.preload(user, bookmarks: :activity)
|
||||
|
||||
conn
|
||||
|> put_view(StatusView)
|
||||
|> try_render("status.json", %{activity: activity, for: user, as: :activity})
|
||||
|
|
@ -1081,6 +1101,8 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
|
|||
ActivityPub.fetch_activities([], params)
|
||||
|> Enum.reverse()
|
||||
|
||||
user = Repo.preload(user, bookmarks: :activity)
|
||||
|
||||
conn
|
||||
|> add_link_headers(:favourites, activities)
|
||||
|> put_view(StatusView)
|
||||
|
|
@ -1124,15 +1146,20 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
|
|||
end
|
||||
end
|
||||
|
||||
def bookmarks(%{assigns: %{user: user}} = conn, _) do
|
||||
def bookmarks(%{assigns: %{user: user}} = conn, params) do
|
||||
user = User.get_cached_by_id(user.id)
|
||||
user = Repo.preload(user, bookmarks: :activity)
|
||||
|
||||
bookmarks =
|
||||
Bookmark.for_user_query(user.id)
|
||||
|> Pagination.fetch_paginated(params)
|
||||
|
||||
activities =
|
||||
user.bookmarks
|
||||
|> Enum.map(fn id -> Activity.get_create_by_object_ap_id(id) end)
|
||||
|> Enum.reverse()
|
||||
bookmarks
|
||||
|> Enum.map(fn b -> b.activity end)
|
||||
|
||||
conn
|
||||
|> add_link_headers(:bookmarks, bookmarks)
|
||||
|> put_view(StatusView)
|
||||
|> render("index.json", %{activities: activities, for: user, as: :activity})
|
||||
end
|
||||
|
|
@ -1238,6 +1265,8 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
|
|||
|> ActivityPub.fetch_activities_bounded(following, params)
|
||||
|> Enum.reverse()
|
||||
|
||||
user = Repo.preload(user, bookmarks: :activity)
|
||||
|
||||
conn
|
||||
|> put_view(StatusView)
|
||||
|> render("index.json", %{activities: activities, for: user, as: :activity})
|
||||
|
|
|
|||
|
|
@ -113,21 +113,23 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do
|
|||
bot: bot,
|
||||
source: %{
|
||||
note: "",
|
||||
privacy: user_info.default_scope,
|
||||
sensitive: false
|
||||
sensitive: false,
|
||||
pleroma: %{}
|
||||
},
|
||||
|
||||
# Pleroma extension
|
||||
pleroma:
|
||||
%{
|
||||
pleroma: %{
|
||||
confirmation_pending: user_info.confirmation_pending,
|
||||
tags: user.tags,
|
||||
is_moderator: user.info.is_moderator,
|
||||
is_admin: user.info.is_admin,
|
||||
hide_followers: user.info.hide_followers,
|
||||
hide_follows: user.info.hide_follows,
|
||||
hide_favorites: user.info.hide_favorites,
|
||||
relationship: relationship
|
||||
}
|
||||
|> with_notification_settings(user, opts[:for])
|
||||
}
|
||||
|> maybe_put_role(user, opts[:for])
|
||||
|> maybe_put_settings(user, opts[:for], user_info)
|
||||
|> maybe_put_notification_settings(user, opts[:for])
|
||||
end
|
||||
|
||||
defp username_from_nickname(string) when is_binary(string) do
|
||||
|
|
@ -136,9 +138,37 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do
|
|||
|
||||
defp username_from_nickname(_), do: nil
|
||||
|
||||
defp with_notification_settings(data, %User{id: user_id} = user, %User{id: user_id}) do
|
||||
Map.put(data, :notification_settings, user.info.notification_settings)
|
||||
defp maybe_put_settings(
|
||||
data,
|
||||
%User{id: user_id} = user,
|
||||
%User{id: user_id},
|
||||
user_info
|
||||
) do
|
||||
data
|
||||
|> Kernel.put_in([:source, :privacy], user_info.default_scope)
|
||||
|> Kernel.put_in([:source, :pleroma, :show_role], user.info.show_role)
|
||||
|> Kernel.put_in([:source, :pleroma, :no_rich_text], user.info.no_rich_text)
|
||||
end
|
||||
|
||||
defp with_notification_settings(data, _, _), do: data
|
||||
defp maybe_put_settings(data, _, _, _), do: data
|
||||
|
||||
defp maybe_put_role(data, %User{info: %{show_role: true}} = user, _) do
|
||||
data
|
||||
|> Kernel.put_in([:pleroma, :is_admin], user.info.is_admin)
|
||||
|> Kernel.put_in([:pleroma, :is_moderator], user.info.is_moderator)
|
||||
end
|
||||
|
||||
defp maybe_put_role(data, %User{id: user_id} = user, %User{id: user_id}) do
|
||||
data
|
||||
|> Kernel.put_in([:pleroma, :is_admin], user.info.is_admin)
|
||||
|> Kernel.put_in([:pleroma, :is_moderator], user.info.is_moderator)
|
||||
end
|
||||
|
||||
defp maybe_put_role(data, _, _), do: data
|
||||
|
||||
defp maybe_put_notification_settings(data, %User{id: user_id} = user, %User{id: user_id}) do
|
||||
Kernel.put_in(data, [:pleroma, :notification_settings], user.info.notification_settings)
|
||||
end
|
||||
|
||||
defp maybe_put_notification_settings(data, _, _), do: data
|
||||
end
|
||||
|
|
|
|||
|
|
@ -85,7 +85,8 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
|
|||
|
||||
activity_object = Object.normalize(activity)
|
||||
favorited = opts[:for] && opts[:for].ap_id in (activity_object.data["likes"] || [])
|
||||
bookmarked = opts[:for] && activity_object.data["id"] in opts[:for].bookmarks
|
||||
|
||||
bookmarked = opts[:for] && CommonAPI.bookmarked?(opts[:for], reblogged_activity)
|
||||
|
||||
mentions =
|
||||
activity.recipients
|
||||
|
|
@ -148,7 +149,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
|
|||
|
||||
favorited = opts[:for] && opts[:for].ap_id in (object.data["likes"] || [])
|
||||
|
||||
bookmarked = opts[:for] && object.data["id"] in opts[:for].bookmarks
|
||||
bookmarked = opts[:for] && CommonAPI.bookmarked?(opts[:for], activity)
|
||||
|
||||
attachment_data = object.data["attachment"] || []
|
||||
attachments = render_many(attachment_data, StatusView, "attachment.json", as: :attachment)
|
||||
|
|
|
|||
|
|
@ -13,10 +13,23 @@ defmodule Pleroma.Web.MediaProxy do
|
|||
|
||||
def url(url) do
|
||||
config = Application.get_env(:pleroma, :media_proxy, [])
|
||||
domain = URI.parse(url).host
|
||||
|
||||
if !Keyword.get(config, :enabled, false) or String.starts_with?(url, Pleroma.Web.base_url()) do
|
||||
cond do
|
||||
!Keyword.get(config, :enabled, false) or String.starts_with?(url, Pleroma.Web.base_url()) ->
|
||||
url
|
||||
else
|
||||
|
||||
Enum.any?(Pleroma.Config.get([:media_proxy, :whitelist]), fn pattern ->
|
||||
String.equivalent?(domain, pattern)
|
||||
end) ->
|
||||
url
|
||||
|
||||
true ->
|
||||
encode_url(url)
|
||||
end
|
||||
end
|
||||
|
||||
def encode_url(url) do
|
||||
secret = Application.get_env(:pleroma, Pleroma.Web.Endpoint)[:secret_key_base]
|
||||
|
||||
# Must preserve `%2F` for compatibility with S3
|
||||
|
|
@ -37,7 +50,6 @@ defmodule Pleroma.Web.MediaProxy do
|
|||
|
||||
build_url(sig64, base64, filename(url))
|
||||
end
|
||||
end
|
||||
|
||||
def decode_url(sig, url) do
|
||||
secret = Application.get_env(:pleroma, Pleroma.Web.Endpoint)[:secret_key_base]
|
||||
|
|
|
|||
|
|
@ -74,7 +74,8 @@ defmodule Pleroma.Web.TwitterAPI.UserView do
|
|||
|> Enum.filter(fn %{"type" => t} -> t == "PropertyValue" end)
|
||||
|> Enum.map(fn fields -> Map.take(fields, ["name", "value"]) end)
|
||||
|
||||
data = %{
|
||||
data =
|
||||
%{
|
||||
"created_at" => user.inserted_at |> Utils.format_naive_asctime(),
|
||||
"description" => HTML.strip_tags((user.bio || "") |> String.replace("<br>", "\n")),
|
||||
"description_html" => HTML.filter_tags(user.bio, User.html_filter_policy(for_user)),
|
||||
|
|
@ -95,10 +96,6 @@ defmodule Pleroma.Web.TwitterAPI.UserView do
|
|||
"profile_image_url_https" => image,
|
||||
"profile_image_url_profile_size" => image,
|
||||
"profile_image_url_original" => image,
|
||||
"rights" => %{
|
||||
"delete_others_notice" => !!user.info.is_moderator,
|
||||
"admin" => !!user.info.is_admin
|
||||
},
|
||||
"screen_name" => user.nickname,
|
||||
"statuses_count" => user_info[:note_count],
|
||||
"statusnet_profile_url" => user.ap_id,
|
||||
|
|
@ -106,8 +103,6 @@ defmodule Pleroma.Web.TwitterAPI.UserView do
|
|||
"background_image" => image_url(user.info.background) |> MediaProxy.url(),
|
||||
"is_local" => user.local,
|
||||
"locked" => user.info.locked,
|
||||
"default_scope" => user.info.default_scope,
|
||||
"no_rich_text" => user.info.no_rich_text,
|
||||
"hide_followers" => user.info.hide_followers,
|
||||
"hide_follows" => user.info.hide_follows,
|
||||
"fields" => fields,
|
||||
|
|
@ -120,6 +115,7 @@ defmodule Pleroma.Web.TwitterAPI.UserView do
|
|||
}
|
||||
|> maybe_with_activation_status(user, for_user)
|
||||
}
|
||||
|> maybe_with_user_settings(user, for_user)
|
||||
|
||||
data =
|
||||
if(user.info.is_admin || user.info.is_moderator,
|
||||
|
|
@ -141,15 +137,35 @@ defmodule Pleroma.Web.TwitterAPI.UserView do
|
|||
defp maybe_with_activation_status(data, _, _), do: data
|
||||
|
||||
defp maybe_with_role(data, %User{id: id} = user, %User{id: id}) do
|
||||
Map.merge(data, %{"role" => role(user), "show_role" => user.info.show_role})
|
||||
Map.merge(data, %{
|
||||
"role" => role(user),
|
||||
"show_role" => user.info.show_role,
|
||||
"rights" => %{
|
||||
"delete_others_notice" => !!user.info.is_moderator,
|
||||
"admin" => !!user.info.is_admin
|
||||
}
|
||||
})
|
||||
end
|
||||
|
||||
defp maybe_with_role(data, %User{info: %{show_role: true}} = user, _user) do
|
||||
Map.merge(data, %{"role" => role(user)})
|
||||
Map.merge(data, %{
|
||||
"role" => role(user),
|
||||
"rights" => %{
|
||||
"delete_others_notice" => !!user.info.is_moderator,
|
||||
"admin" => !!user.info.is_admin
|
||||
}
|
||||
})
|
||||
end
|
||||
|
||||
defp maybe_with_role(data, _, _), do: data
|
||||
|
||||
defp maybe_with_user_settings(data, %User{info: info, id: id} = _user, %User{id: id}) do
|
||||
data
|
||||
|> Kernel.put_in(["default_scope"], info.default_scope)
|
||||
|> Kernel.put_in(["no_rich_text"], info.no_rich_text)
|
||||
end
|
||||
|
||||
defp maybe_with_user_settings(data, _, _), do: data
|
||||
defp role(%User{info: %{:is_admin => true}}), do: "admin"
|
||||
defp role(%User{info: %{:is_moderator => true}}), do: "moderator"
|
||||
defp role(_), do: "member"
|
||||
|
|
|
|||
1
mix.exs
1
mix.exs
|
|
@ -84,6 +84,7 @@ defmodule Pleroma.Mixfile do
|
|||
{:ex_aws, "~> 2.0"},
|
||||
{:ex_aws_s3, "~> 2.0"},
|
||||
{:earmark, "~> 1.3"},
|
||||
{:bbcode, "~> 0.1"},
|
||||
{:ex_machina, "~> 2.3", only: :test},
|
||||
{:credo, "~> 0.9.3", only: [:dev, :test]},
|
||||
{:mock, "~> 0.3.1", only: :test},
|
||||
|
|
|
|||
1
mix.lock
1
mix.lock
|
|
@ -2,6 +2,7 @@
|
|||
"accept": {:hex, :accept, "0.3.5", "b33b127abca7cc948bbe6caa4c263369abf1347cfa9d8e699c6d214660f10cd1", [:rebar3], [], "hexpm"},
|
||||
"auto_linker": {:git, "https://git.pleroma.social/pleroma/auto_linker.git", "90613b4bae875a3610c275b7056b61ffdd53210d", [ref: "90613b4bae875a3610c275b7056b61ffdd53210d"]},
|
||||
"base64url": {:hex, :base64url, "0.0.1", "36a90125f5948e3afd7be97662a1504b934dd5dac78451ca6e9abf85a10286be", [:rebar], [], "hexpm"},
|
||||
"bbcode": {:hex, :bbcode, "0.1.0", "400e618b640b635261611d7fb7f79d104917fc5b084aae371ab6b08477cb035b", [:mix], [{:nimble_parsec, "~> 0.5", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm"},
|
||||
"bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], [], "hexpm"},
|
||||
"cachex": {:hex, :cachex, "3.0.2", "1351caa4e26e29f7d7ec1d29b53d6013f0447630bbf382b4fb5d5bad0209f203", [:mix], [{:eternal, "~> 1.2", [hex: :eternal, repo: "hexpm", optional: false]}, {:unsafe, "~> 1.0", [hex: :unsafe, repo: "hexpm", optional: false]}], "hexpm"},
|
||||
"calendar": {:hex, :calendar, "0.17.4", "22c5e8d98a4db9494396e5727108dffb820ee0d18fed4b0aa8ab76e4f5bc32f1", [:mix], [{:tzdata, "~> 0.5.8 or ~> 0.1.201603", [hex: :tzdata, repo: "hexpm", optional: false]}], "hexpm"},
|
||||
|
|
|
|||
14
priv/repo/migrations/20190413082658_create_bookmarks.exs
Normal file
14
priv/repo/migrations/20190413082658_create_bookmarks.exs
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
defmodule Pleroma.Repo.Migrations.CreateBookmarks do
|
||||
use Ecto.Migration
|
||||
|
||||
def change do
|
||||
create table(:bookmarks) do
|
||||
add(:user_id, references(:users, type: :uuid, on_delete: :delete_all))
|
||||
add(:activity_id, references(:activities, type: :uuid, on_delete: :delete_all))
|
||||
|
||||
timestamps()
|
||||
end
|
||||
|
||||
create(unique_index(:bookmarks, [:user_id, :activity_id]))
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
defmodule Pleroma.Repo.Migrations.MigrateOldBookmarks do
|
||||
use Ecto.Migration
|
||||
import Ecto.Query
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.Bookmark
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Repo
|
||||
|
||||
def change do
|
||||
query =
|
||||
from(u in User,
|
||||
where: u.local == true,
|
||||
where: fragment("array_length(bookmarks, 1)") > 0,
|
||||
select: %{id: u.id, bookmarks: fragment("bookmarks")}
|
||||
)
|
||||
|
||||
Repo.stream(query)
|
||||
|> Enum.each(fn %{id: user_id, bookmarks: bookmarks} ->
|
||||
Enum.each(bookmarks, fn ap_id ->
|
||||
activity = Activity.get_create_by_object_ap_id(ap_id)
|
||||
{:ok, _} = Bookmark.create(user_id, activity.id)
|
||||
end)
|
||||
end)
|
||||
|
||||
alter table(:users) do
|
||||
remove(:bookmarks)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1 +1 @@
|
|||
<!DOCTYPE html><html lang=en><head><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><title>Pleroma</title><!--server-generated-meta--><link rel=icon type=image/png href=/favicon.png><link rel=stylesheet href=/static/font/css/fontello.css><link rel=stylesheet href=/static/font/css/animation.css><link href=/static/css/app.ea66966b753e709d7ce58f910a2c003e.css rel=stylesheet></head><body style="display: none"><div id=app></div><script type=text/javascript src=/static/js/manifest.0b2f423dda42f0dbbf65.js></script><script type=text/javascript src=/static/js/vendor.e4475fde034685231799.js></script><script type=text/javascript src=/static/js/app.77434de4e756a5d79672.js></script></body></html>
|
||||
<!DOCTYPE html><html lang=en><head><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><title>Pleroma</title><!--server-generated-meta--><link rel=icon type=image/png href=/favicon.png><link rel=stylesheet href=/static/font/css/fontello.css><link rel=stylesheet href=/static/font/css/animation.css><link href=/static/css/app.a81578273cb4c57163939ab70c80eb06.css rel=stylesheet></head><body style="display: none"><div id=app></div><script type=text/javascript src=/static/js/manifest.bf15f24d205c8cf4ee4a.js></script><script type=text/javascript src=/static/js/vendor.0d1eeaf25aa1d2fc51b0.js></script><script type=text/javascript src=/static/js/app.c914d9a57d5da7aa5553.js></script></body></html>
|
||||
|
|
@ -8,7 +8,6 @@
|
|||
"redirectRootLogin": "/main/friends",
|
||||
"chatDisabled": false,
|
||||
"showInstanceSpecificPanel": false,
|
||||
"scopeOptionsEnabled": false,
|
||||
"formattingOptionsEnabled": false,
|
||||
"collapseMessageWithSubject": false,
|
||||
"scopeCopy": true,
|
||||
|
|
@ -21,5 +20,6 @@
|
|||
"webPushNotifications": false,
|
||||
"noAttachmentLinks": false,
|
||||
"nsfwCensorImage": "",
|
||||
"showFeaturesPanel": true
|
||||
"showFeaturesPanel": true,
|
||||
"minimalScopesMode": false
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
0
priv/static/static/font/LICENSE.txt
Executable file → Normal file
0
priv/static/static/font/LICENSE.txt
Executable file → Normal file
0
priv/static/static/font/README.txt
Executable file → Normal file
0
priv/static/static/font/README.txt
Executable file → Normal file
12
priv/static/static/font/config.json
Executable file → Normal file
12
priv/static/static/font/config.json
Executable file → Normal file
|
|
@ -239,6 +239,18 @@
|
|||
"css": "pencil",
|
||||
"code": 59416,
|
||||
"src": "fontawesome"
|
||||
},
|
||||
{
|
||||
"uid": "671f29fa10dda08074a4c6a341bb4f39",
|
||||
"css": "bell-alt",
|
||||
"code": 61683,
|
||||
"src": "fontawesome"
|
||||
},
|
||||
{
|
||||
"uid": "5bb103cd29de77e0e06a52638527b575",
|
||||
"css": "wrench",
|
||||
"code": 59418,
|
||||
"src": "fontawesome"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -24,6 +24,8 @@
|
|||
.icon-adjust:before { content: '\e816'; } /* '' */
|
||||
.icon-edit:before { content: '\e817'; } /* '' */
|
||||
.icon-pencil:before { content: '\e818'; } /* '' */
|
||||
.icon-verified:before { content: '\e819'; } /* '' */
|
||||
.icon-wrench:before { content: '\e81a'; } /* '' */
|
||||
.icon-spin3:before { content: '\e832'; } /* '' */
|
||||
.icon-spin4:before { content: '\e834'; } /* '' */
|
||||
.icon-link-ext:before { content: '\f08e'; } /* '' */
|
||||
|
|
@ -31,6 +33,7 @@
|
|||
.icon-menu:before { content: '\f0c9'; } /* '' */
|
||||
.icon-mail-alt:before { content: '\f0e0'; } /* '' */
|
||||
.icon-comment-empty:before { content: '\f0e5'; } /* '' */
|
||||
.icon-bell-alt:before { content: '\f0f3'; } /* '' */
|
||||
.icon-plus-squared:before { content: '\f0fe'; } /* '' */
|
||||
.icon-reply:before { content: '\f112'; } /* '' */
|
||||
.icon-lock-open-alt:before { content: '\f13e'; } /* '' */
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -24,6 +24,8 @@
|
|||
.icon-adjust { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-edit { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-pencil { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-verified { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-wrench { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-spin3 { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-spin4 { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-link-ext { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
|
|
@ -31,6 +33,7 @@
|
|||
.icon-menu { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-mail-alt { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-comment-empty { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-bell-alt { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-plus-squared { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-reply { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-lock-open-alt { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
|
|
|
|||
3
priv/static/static/font/css/fontello-ie7.css
vendored
3
priv/static/static/font/css/fontello-ie7.css
vendored
|
|
@ -35,6 +35,8 @@
|
|||
.icon-adjust { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-edit { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-pencil { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-verified { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-wrench { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-spin3 { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-spin4 { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-link-ext { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
|
|
@ -42,6 +44,7 @@
|
|||
.icon-menu { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-mail-alt { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-comment-empty { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-bell-alt { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-plus-squared { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-reply { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-lock-open-alt { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
|
|
|
|||
17
priv/static/static/font/css/fontello.css
vendored
17
priv/static/static/font/css/fontello.css
vendored
|
|
@ -1,11 +1,11 @@
|
|||
@font-face {
|
||||
font-family: 'fontello';
|
||||
src: url('../font/fontello.eot?40679575');
|
||||
src: url('../font/fontello.eot?40679575#iefix') format('embedded-opentype'),
|
||||
url('../font/fontello.woff2?40679575') format('woff2'),
|
||||
url('../font/fontello.woff?40679575') format('woff'),
|
||||
url('../font/fontello.ttf?40679575') format('truetype'),
|
||||
url('../font/fontello.svg?40679575#fontello') format('svg');
|
||||
src: url('../font/fontello.eot?11878820');
|
||||
src: url('../font/fontello.eot?11878820#iefix') format('embedded-opentype'),
|
||||
url('../font/fontello.woff2?11878820') format('woff2'),
|
||||
url('../font/fontello.woff?11878820') format('woff'),
|
||||
url('../font/fontello.ttf?11878820') format('truetype'),
|
||||
url('../font/fontello.svg?11878820#fontello') format('svg');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
|
@ -15,7 +15,7 @@
|
|||
@media screen and (-webkit-min-device-pixel-ratio:0) {
|
||||
@font-face {
|
||||
font-family: 'fontello';
|
||||
src: url('../font/fontello.svg?40679575#fontello') format('svg');
|
||||
src: url('../font/fontello.svg?11878820#fontello') format('svg');
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
|
@ -80,6 +80,8 @@
|
|||
.icon-adjust:before { content: '\e816'; } /* '' */
|
||||
.icon-edit:before { content: '\e817'; } /* '' */
|
||||
.icon-pencil:before { content: '\e818'; } /* '' */
|
||||
.icon-verified:before { content: '\e819'; } /* '' */
|
||||
.icon-wrench:before { content: '\e81a'; } /* '' */
|
||||
.icon-spin3:before { content: '\e832'; } /* '' */
|
||||
.icon-spin4:before { content: '\e834'; } /* '' */
|
||||
.icon-link-ext:before { content: '\f08e'; } /* '' */
|
||||
|
|
@ -87,6 +89,7 @@
|
|||
.icon-menu:before { content: '\f0c9'; } /* '' */
|
||||
.icon-mail-alt:before { content: '\f0e0'; } /* '' */
|
||||
.icon-comment-empty:before { content: '\f0e5'; } /* '' */
|
||||
.icon-bell-alt:before { content: '\f0f3'; } /* '' */
|
||||
.icon-plus-squared:before { content: '\f0fe'; } /* '' */
|
||||
.icon-reply:before { content: '\f112'; } /* '' */
|
||||
.icon-lock-open-alt:before { content: '\f13e'; } /* '' */
|
||||
|
|
|
|||
|
|
@ -229,11 +229,11 @@ body {
|
|||
}
|
||||
@font-face {
|
||||
font-family: 'fontello';
|
||||
src: url('./font/fontello.eot?50378338');
|
||||
src: url('./font/fontello.eot?50378338#iefix') format('embedded-opentype'),
|
||||
url('./font/fontello.woff?50378338') format('woff'),
|
||||
url('./font/fontello.ttf?50378338') format('truetype'),
|
||||
url('./font/fontello.svg?50378338#fontello') format('svg');
|
||||
src: url('./font/fontello.eot?60799712');
|
||||
src: url('./font/fontello.eot?60799712#iefix') format('embedded-opentype'),
|
||||
url('./font/fontello.woff?60799712') format('woff'),
|
||||
url('./font/fontello.ttf?60799712') format('truetype'),
|
||||
url('./font/fontello.svg?60799712#fontello') format('svg');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
|
@ -335,24 +335,29 @@ body {
|
|||
</div>
|
||||
<div class="row">
|
||||
<div class="the-icons span3" title="Code: 0xe818"><i class="demo-icon icon-pencil"></i> <span class="i-name">icon-pencil</span><span class="i-code">0xe818</span></div>
|
||||
<div class="the-icons span3" title="Code: 0xe819"><i class="demo-icon icon-verified"></i> <span class="i-name">icon-verified</span><span class="i-code">0xe819</span></div>
|
||||
<div class="the-icons span3" title="Code: 0xe81a"><i class="demo-icon icon-wrench"></i> <span class="i-name">icon-wrench</span><span class="i-code">0xe81a</span></div>
|
||||
<div class="the-icons span3" title="Code: 0xe832"><i class="demo-icon icon-spin3 animate-spin"></i> <span class="i-name">icon-spin3</span><span class="i-code">0xe832</span></div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="the-icons span3" title="Code: 0xe834"><i class="demo-icon icon-spin4 animate-spin"></i> <span class="i-name">icon-spin4</span><span class="i-code">0xe834</span></div>
|
||||
<div class="the-icons span3" title="Code: 0xf08e"><i class="demo-icon icon-link-ext"></i> <span class="i-name">icon-link-ext</span><span class="i-code">0xf08e</span></div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="the-icons span3" title="Code: 0xf08f"><i class="demo-icon icon-link-ext-alt"></i> <span class="i-name">icon-link-ext-alt</span><span class="i-code">0xf08f</span></div>
|
||||
<div class="the-icons span3" title="Code: 0xf0c9"><i class="demo-icon icon-menu"></i> <span class="i-name">icon-menu</span><span class="i-code">0xf0c9</span></div>
|
||||
<div class="the-icons span3" title="Code: 0xf0e0"><i class="demo-icon icon-mail-alt"></i> <span class="i-name">icon-mail-alt</span><span class="i-code">0xf0e0</span></div>
|
||||
<div class="the-icons span3" title="Code: 0xf0e5"><i class="demo-icon icon-comment-empty"></i> <span class="i-name">icon-comment-empty</span><span class="i-code">0xf0e5</span></div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="the-icons span3" title="Code: 0xf0e0"><i class="demo-icon icon-mail-alt"></i> <span class="i-name">icon-mail-alt</span><span class="i-code">0xf0e0</span></div>
|
||||
<div class="the-icons span3" title="Code: 0xf0e5"><i class="demo-icon icon-comment-empty"></i> <span class="i-name">icon-comment-empty</span><span class="i-code">0xf0e5</span></div>
|
||||
<div class="the-icons span3" title="Code: 0xf0f3"><i class="demo-icon icon-bell-alt"></i> <span class="i-name">icon-bell-alt</span><span class="i-code">0xf0f3</span></div>
|
||||
<div class="the-icons span3" title="Code: 0xf0fe"><i class="demo-icon icon-plus-squared"></i> <span class="i-name">icon-plus-squared</span><span class="i-code">0xf0fe</span></div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="the-icons span3" title="Code: 0xf112"><i class="demo-icon icon-reply"></i> <span class="i-name">icon-reply</span><span class="i-code">0xf112</span></div>
|
||||
<div class="the-icons span3" title="Code: 0xf13e"><i class="demo-icon icon-lock-open-alt"></i> <span class="i-name">icon-lock-open-alt</span><span class="i-code">0xf13e</span></div>
|
||||
<div class="the-icons span3" title="Code: 0xf144"><i class="demo-icon icon-play-circled"></i> <span class="i-name">icon-play-circled</span><span class="i-code">0xf144</span></div>
|
||||
<div class="the-icons span3" title="Code: 0xf164"><i class="demo-icon icon-thumbs-up-alt"></i> <span class="i-name">icon-thumbs-up-alt</span><span class="i-code">0xf164</span></div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="the-icons span3" title="Code: 0xf164"><i class="demo-icon icon-thumbs-up-alt"></i> <span class="i-name">icon-thumbs-up-alt</span><span class="i-code">0xf164</span></div>
|
||||
<div class="the-icons span3" title="Code: 0xf1e5"><i class="demo-icon icon-binoculars"></i> <span class="i-name">icon-binoculars</span><span class="i-code">0xf1e5</span></div>
|
||||
<div class="the-icons span3" title="Code: 0xf234"><i class="demo-icon icon-user-plus"></i> <span class="i-name">icon-user-plus</span><span class="i-code">0xf234</span></div>
|
||||
</div>
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -56,6 +56,10 @@
|
|||
|
||||
<glyph glyph-name="pencil" unicode="" d="M203 0l50 51-131 131-51-51v-60h72v-71h60z m291 518q0 12-12 12-5 0-9-4l-303-302q-4-4-4-10 0-12 13-12 5 0 9 4l303 302q3 4 3 10z m-30 107l232-232-464-465h-232v233z m381-54q0-29-20-50l-93-93-232 233 93 92q20 21 50 21 29 0 51-21l131-131q20-22 20-51z" horiz-adv-x="857.1" />
|
||||
|
||||
<glyph glyph-name="verified" unicode="" d="M926 453l-19 13c-21 14-30 41-23 65l6 22c10 34-13 69-48 75l-23 4c-25 4-45 23-49 48l-4 23c-6 35-41 57-75 47l-22-7c-24-7-51 2-65 22l-14 20c-21 29-62 33-88 9l-17-16c-19-17-46-21-69-8l-20 11c-31 17-70 3-84-30l-9-22c-9-24-33-39-58-37l-23 1c-36 2-65-28-62-63l2-23c2-25-13-49-36-59l-21-9c-33-14-46-53-29-84l12-20c13-22 10-50-7-69l-15-17c-24-27-19-68 11-88l19-13c21-14 30-41 23-65l-9-23c-10-34 13-69 48-75l23-4c25-4 45-23 49-48l4-23c6-35 41-57 75-47l22 7c24 7 51-2 65-22l14-19c21-29 62-33 88-9l17 16c19 17 46 21 69 8l20-11c31-17 70-3 84 30l9 22c9 24 33 39 58 37l23-1c36-2 65 28 62 63l-1 23c-2 25 13 49 36 59l21 9c33 14 46 53 29 84l-12 20c-13 22-10 50 7 69l15 17c25 26 20 68-9 88z m-399-189l-82-81-81 82-78 79 82 81 78-79 187 186 81-82-187-186z" horiz-adv-x="1000" />
|
||||
|
||||
<glyph glyph-name="wrench" unicode="" d="M214 36q0 14-10 25t-25 10-25-10-11-25 11-25 25-11 25 11 10 25z m360 234l-381-381q-21-20-50-20-29 0-51 20l-59 61q-21 20-21 50 0 29 21 51l380 380q22-55 64-97t97-64z m354 243q0-22-13-59-27-75-92-122t-144-46q-104 0-177 73t-73 177 73 176 177 74q32 0 67-10t60-26q9-6 9-15t-9-16l-163-94v-125l108-60q2 2 44 27t75 45 40 20q8 0 13-5t5-14z" horiz-adv-x="928.6" />
|
||||
|
||||
<glyph glyph-name="spin3" unicode="" d="M494 857c-266 0-483-210-494-472-1-19 13-20 13-20l84 0c16 0 19 10 19 18 10 199 176 358 378 358 107 0 205-45 273-118l-58-57c-11-12-11-27 5-31l247-50c21-5 46 11 37 44l-58 227c-2 9-16 22-29 13l-65-60c-89 91-214 148-352 148z m409-508c-16 0-19-10-19-18-10-199-176-358-377-358-108 0-205 45-274 118l59 57c10 12 10 27-5 31l-248 50c-21 5-46-11-37-44l58-227c2-9 16-22 30-13l64 60c89-91 214-148 353-148 265 0 482 210 493 473 1 18-13 19-13 19l-84 0z" horiz-adv-x="1000" />
|
||||
|
||||
<glyph glyph-name="spin4" unicode="" d="M498 857c-114 0-228-39-320-116l0 0c173 140 428 130 588-31 134-134 164-332 89-495-10-29-5-50 12-68 21-20 61-23 84 0 3 3 12 15 15 24 71 180 33 393-112 539-99 98-228 147-356 147z m-409-274c-14 0-29-5-39-16-3-3-13-15-15-24-71-180-34-393 112-539 185-185 479-195 676-31l0 0c-173-140-428-130-589 31-134 134-163 333-89 495 11 29 6 50-12 68-11 11-27 17-44 16z" horiz-adv-x="1001" />
|
||||
|
|
@ -70,6 +74,8 @@
|
|||
|
||||
<glyph glyph-name="comment-empty" unicode="" d="M500 643q-114 0-213-39t-157-105-59-142q0-62 40-119t113-98l48-28-15-53q-13-51-39-97 85 36 154 96l24 21 32-3q38-5 72-5 114 0 213 39t157 105 59 142-59 142-157 105-213 39z m500-286q0-97-67-179t-182-130-251-48q-39 0-81 4-110-97-257-135-27-8-63-12h-3q-8 0-15 6t-9 15v1q-2 2 0 6t1 6 2 5l4 5t4 5 4 5q4 5 17 19t20 22 17 22 18 28 15 33 15 42q-88 50-138 123t-51 157q0 97 67 179t182 130 251 48 251-48 182-130 67-179z" horiz-adv-x="1000" />
|
||||
|
||||
<glyph glyph-name="bell-alt" unicode="" d="M509-89q0 8-9 8-33 0-57 24t-23 57q0 9-9 9t-9-9q0-41 29-70t69-28q9 0 9 9z m455 160q0-29-21-50t-50-21h-250q0-59-42-101t-101-42-101 42-42 101h-250q-29 0-50 21t-21 50q28 24 51 49t47 67 42 89 27 115 11 145q0 84 66 157t171 89q-5 10-5 21 0 23 16 38t38 16 38-16 16-38q0-11-5-21 106-16 171-89t66-157q0-78 11-145t28-115 41-89 48-67 50-49z" horiz-adv-x="1000" />
|
||||
|
||||
<glyph glyph-name="plus-squared" unicode="" d="M714 321v72q0 14-10 25t-25 10h-179v179q0 15-11 25t-25 11h-71q-15 0-25-11t-11-25v-179h-178q-15 0-25-10t-11-25v-72q0-14 11-25t25-10h178v-179q0-14 11-25t25-11h71q15 0 25 11t11 25v179h179q14 0 25 10t10 25z m143 304v-536q0-66-47-113t-114-48h-535q-67 0-114 48t-47 113v536q0 66 47 113t114 48h535q67 0 114-48t47-113z" horiz-adv-x="857.1" />
|
||||
|
||||
<glyph glyph-name="reply" unicode="" d="M1000 232q0-93-71-252-1-4-6-13t-7-17-7-12q-7-10-16-10-8 0-13 6t-5 14q0 5 1 15t2 13q3 38 3 69 0 56-10 101t-27 77-45 56-59 39-74 24-86 12-98 3h-125v-143q0-14-10-25t-26-11-25 11l-285 286q-11 10-11 25t11 25l285 286q11 10 25 10t26-10 10-25v-143h125q398 0 488-225 30-75 30-186z" horiz-adv-x="1000" />
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 20 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 34 KiB |
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
20
priv/static/static/js/app.c914d9a57d5da7aa5553.js
Normal file
20
priv/static/static/js/app.c914d9a57d5da7aa5553.js
Normal file
File diff suppressed because one or more lines are too long
1
priv/static/static/js/app.c914d9a57d5da7aa5553.js.map
Normal file
1
priv/static/static/js/app.c914d9a57d5da7aa5553.js.map
Normal file
File diff suppressed because one or more lines are too long
|
|
@ -1,2 +0,0 @@
|
|||
!function(e){function t(r){if(n[r])return n[r].exports;var a=n[r]={exports:{},id:r,loaded:!1};return e[r].call(a.exports,a,a.exports,t),a.loaded=!0,a.exports}var r=window.webpackJsonp;window.webpackJsonp=function(o,p){for(var c,l,s=0,i=[];s<o.length;s++)l=o[s],a[l]&&i.push.apply(i,a[l]),a[l]=0;for(c in p)Object.prototype.hasOwnProperty.call(p,c)&&(e[c]=p[c]);for(r&&r(o,p);i.length;)i.shift().call(null,t);if(p[0])return n[0]=0,t(0)};var n={},a={0:0};t.e=function(e,r){if(0===a[e])return r.call(null,t);if(void 0!==a[e])a[e].push(r);else{a[e]=[r];var n=document.getElementsByTagName("head")[0],o=document.createElement("script");o.type="text/javascript",o.charset="utf-8",o.async=!0,o.src=t.p+"static/js/"+e+"."+{1:"e4475fde034685231799",2:"77434de4e756a5d79672"}[e]+".js",n.appendChild(o)}},t.m=e,t.c=n,t.p="/"}([]);
|
||||
//# sourceMappingURL=manifest.0b2f423dda42f0dbbf65.js.map
|
||||
2
priv/static/static/js/manifest.bf15f24d205c8cf4ee4a.js
Normal file
2
priv/static/static/js/manifest.bf15f24d205c8cf4ee4a.js
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
!function(e){function t(a){if(r[a])return r[a].exports;var n=r[a]={exports:{},id:a,loaded:!1};return e[a].call(n.exports,n,n.exports,t),n.loaded=!0,n.exports}var a=window.webpackJsonp;window.webpackJsonp=function(o,c){for(var p,l,s=0,d=[];s<o.length;s++)l=o[s],n[l]&&d.push.apply(d,n[l]),n[l]=0;for(p in c)Object.prototype.hasOwnProperty.call(c,p)&&(e[p]=c[p]);for(a&&a(o,c);d.length;)d.shift().call(null,t);if(c[0])return r[0]=0,t(0)};var r={},n={0:0};t.e=function(e,a){if(0===n[e])return a.call(null,t);if(void 0!==n[e])n[e].push(a);else{n[e]=[a];var r=document.getElementsByTagName("head")[0],o=document.createElement("script");o.type="text/javascript",o.charset="utf-8",o.async=!0,o.src=t.p+"static/js/"+e+"."+{1:"0d1eeaf25aa1d2fc51b0",2:"c914d9a57d5da7aa5553"}[e]+".js",r.appendChild(o)}},t.m=e,t.c=r,t.p="/"}([]);
|
||||
//# sourceMappingURL=manifest.bf15f24d205c8cf4ee4a.js.map
|
||||
File diff suppressed because one or more lines are too long
68
priv/static/static/js/vendor.0d1eeaf25aa1d2fc51b0.js
Normal file
68
priv/static/static/js/vendor.0d1eeaf25aa1d2fc51b0.js
Normal file
File diff suppressed because one or more lines are too long
1
priv/static/static/js/vendor.0d1eeaf25aa1d2fc51b0.js.map
Normal file
1
priv/static/static/js/vendor.0d1eeaf25aa1d2fc51b0.js.map
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Binary file not shown.
|
Before Width: | Height: | Size: 748 B After Width: | Height: | Size: 1.3 KiB |
|
|
@ -1,4 +1,4 @@
|
|||
var serviceWorkerOption = {"assets":["/static/img/nsfw.74818f9.png","/static/js/manifest.0b2f423dda42f0dbbf65.js","/static/js/vendor.e4475fde034685231799.js","/static/js/app.77434de4e756a5d79672.js","/static/css/app.ea66966b753e709d7ce58f910a2c003e.css"]};
|
||||
var serviceWorkerOption = {"assets":["/static/img/nsfw.74818f9.png","/static/js/manifest.bf15f24d205c8cf4ee4a.js","/static/js/vendor.0d1eeaf25aa1d2fc51b0.js","/static/js/app.c914d9a57d5da7aa5553.js","/static/css/app.a81578273cb4c57163939ab70c80eb06.css"]};
|
||||
|
||||
!function(e){function n(r){if(t[r])return t[r].exports;var o=t[r]={exports:{},id:r,loaded:!1};return e[r].call(o.exports,o,o.exports,n),o.loaded=!0,o.exports}var t={};return n.m=e,n.c=t,n.p="/",n(0)}([function(e,n,t){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function o(){return u.default.getItem("vuex-lz").then(function(e){return e.config.webPushNotifications})}function i(){return clients.matchAll({includeUncontrolled:!0}).then(function(e){return e.filter(function(e){var n=e.type;return"window"===n})})}var a=t(1),u=r(a);self.addEventListener("push",function(e){e.data&&e.waitUntil(o().then(function(n){return n&&i().then(function(n){var t=e.data.json();if(0===n.length)return self.registration.showNotification(t.title,t)})}))}),self.addEventListener("notificationclick",function(e){e.notification.close(),e.waitUntil(i().then(function(e){for(var n=0;n<e.length;n++){var t=e[n];if("/"===t.url&&"focus"in t)return t.focus()}if(clients.openWindow)return clients.openWindow("/")}))})},function(e,n){/*!
|
||||
localForage -- Offline Storage, Improved
|
||||
|
|
|
|||
52
test/bookmark_test.exs
Normal file
52
test/bookmark_test.exs
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
defmodule Pleroma.BookmarkTest do
|
||||
use Pleroma.DataCase
|
||||
import Pleroma.Factory
|
||||
alias Pleroma.Bookmark
|
||||
alias Pleroma.Web.CommonAPI
|
||||
|
||||
describe "create/2" do
|
||||
test "with valid params" do
|
||||
user = insert(:user)
|
||||
{:ok, activity} = CommonAPI.post(user, %{"status" => "Some cool information"})
|
||||
{:ok, bookmark} = Bookmark.create(user.id, activity.id)
|
||||
assert bookmark.user_id == user.id
|
||||
assert bookmark.activity_id == activity.id
|
||||
end
|
||||
|
||||
test "with invalid params" do
|
||||
{:error, changeset} = Bookmark.create(nil, "")
|
||||
refute changeset.valid?
|
||||
|
||||
assert changeset.errors == [
|
||||
user_id: {"can't be blank", [validation: :required]},
|
||||
activity_id: {"can't be blank", [validation: :required]}
|
||||
]
|
||||
end
|
||||
end
|
||||
|
||||
describe "destroy/2" do
|
||||
test "with valid params" do
|
||||
user = insert(:user)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(user, %{"status" => "Some cool information"})
|
||||
{:ok, _bookmark} = Bookmark.create(user.id, activity.id)
|
||||
|
||||
{:ok, _deleted_bookmark} = Bookmark.destroy(user.id, activity.id)
|
||||
end
|
||||
end
|
||||
|
||||
describe "get/2" do
|
||||
test "gets a bookmark" do
|
||||
user = insert(:user)
|
||||
|
||||
{:ok, activity} =
|
||||
CommonAPI.post(user, %{
|
||||
"status" =>
|
||||
"Scientists Discover The Secret Behind Tenshi Eating A Corndog Being So Cute – Science Daily"
|
||||
})
|
||||
|
||||
{:ok, bookmark} = Bookmark.create(user.id, activity.id)
|
||||
assert bookmark == Bookmark.get(user.id, activity.id)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -177,4 +177,13 @@ defmodule Pleroma.MediaProxyTest do
|
|||
{:ok, decoded} = decode_url(sig, base64)
|
||||
decoded
|
||||
end
|
||||
|
||||
test "mediaproxy whitelist" do
|
||||
Pleroma.Config.put([:media_proxy, :enabled], true)
|
||||
Pleroma.Config.put([:media_proxy, :whitelist], ["google.com", "feld.me"])
|
||||
url = "https://feld.me/foo.png"
|
||||
|
||||
unencoded = url(url)
|
||||
assert unencoded == url
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1125,33 +1125,6 @@ defmodule Pleroma.UserTest do
|
|||
end
|
||||
end
|
||||
|
||||
test "bookmarks" do
|
||||
user = insert(:user)
|
||||
|
||||
{:ok, activity1} =
|
||||
CommonAPI.post(user, %{
|
||||
"status" => "heweoo!"
|
||||
})
|
||||
|
||||
id1 = Object.normalize(activity1).data["id"]
|
||||
|
||||
{:ok, activity2} =
|
||||
CommonAPI.post(user, %{
|
||||
"status" => "heweoo!"
|
||||
})
|
||||
|
||||
id2 = Object.normalize(activity2).data["id"]
|
||||
|
||||
assert {:ok, user_state1} = User.bookmark(user, id1)
|
||||
assert user_state1.bookmarks == [id1]
|
||||
|
||||
assert {:ok, user_state2} = User.unbookmark(user, id1)
|
||||
assert user_state2.bookmarks == []
|
||||
|
||||
assert {:ok, user_state3} = User.bookmark(user, id2)
|
||||
assert user_state3.bookmarks == [id2]
|
||||
end
|
||||
|
||||
test "follower count is updated when a follower is blocked" do
|
||||
user = insert(:user)
|
||||
follower = insert(:user)
|
||||
|
|
|
|||
|
|
@ -215,6 +215,26 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
|
|||
assert User.following?(User.get_cached_by_ap_id(data["actor"]), user)
|
||||
end
|
||||
|
||||
test "it rejects incoming follow requests from blocked users when deny_follow_blocked is enabled" do
|
||||
Pleroma.Config.put([:user, :deny_follow_blocked], true)
|
||||
|
||||
user = insert(:user)
|
||||
target = User.get_or_fetch("http://mastodon.example.org/users/admin")
|
||||
|
||||
{:ok, user} = User.block(user, target)
|
||||
|
||||
data =
|
||||
File.read!("test/fixtures/mastodon-follow-activity.json")
|
||||
|> Poison.decode!()
|
||||
|> Map.put("object", user.ap_id)
|
||||
|
||||
{:ok, %Activity{data: %{"id" => id}}} = Transmogrifier.handle_incoming(data)
|
||||
|
||||
%Activity{} = activity = Activity.get_by_ap_id(id)
|
||||
|
||||
assert activity.data["state"] == "reject"
|
||||
end
|
||||
|
||||
test "it works for incoming follow requests from hubzilla" do
|
||||
user = insert(:user)
|
||||
|
||||
|
|
|
|||
|
|
@ -119,6 +119,31 @@ defmodule Pleroma.Web.CommonAPI.UtilsTest do
|
|||
assert output == expected
|
||||
end
|
||||
|
||||
test "works for bare text/bbcode" do
|
||||
text = "[b]hello world[/b]"
|
||||
expected = "<strong>hello world</strong>"
|
||||
|
||||
{output, [], []} = Utils.format_input(text, "text/bbcode")
|
||||
|
||||
assert output == expected
|
||||
|
||||
text = "[b]hello world![/b]\n\nsecond paragraph!"
|
||||
expected = "<strong>hello world!</strong><br>\n<br>\nsecond paragraph!"
|
||||
|
||||
{output, [], []} = Utils.format_input(text, "text/bbcode")
|
||||
|
||||
assert output == expected
|
||||
|
||||
text = "[b]hello world![/b]\n\n<strong>second paragraph!</strong>"
|
||||
|
||||
expected =
|
||||
"<strong>hello world!</strong><br>\n<br>\n<strong>second paragraph!</strong>"
|
||||
|
||||
{output, [], []} = Utils.format_input(text, "text/bbcode")
|
||||
|
||||
assert output == expected
|
||||
end
|
||||
|
||||
test "works for text/markdown with mentions" do
|
||||
{:ok, user} =
|
||||
UserBuilder.insert(%{nickname: "user__test", ap_id: "http://foo.com/user__test"})
|
||||
|
|
|
|||
|
|
@ -56,14 +56,17 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do
|
|||
bot: false,
|
||||
source: %{
|
||||
note: "",
|
||||
privacy: "public",
|
||||
sensitive: false
|
||||
sensitive: false,
|
||||
pleroma: %{}
|
||||
},
|
||||
pleroma: %{
|
||||
confirmation_pending: false,
|
||||
tags: [],
|
||||
is_admin: false,
|
||||
is_moderator: false,
|
||||
hide_favorites: true,
|
||||
hide_followers: false,
|
||||
hide_follows: false,
|
||||
relationship: %{}
|
||||
}
|
||||
}
|
||||
|
|
@ -81,8 +84,12 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do
|
|||
"follows" => true
|
||||
}
|
||||
|
||||
assert %{pleroma: %{notification_settings: ^notification_settings}} =
|
||||
AccountView.render("account.json", %{user: user, for: user})
|
||||
privacy = user.info.default_scope
|
||||
|
||||
assert %{
|
||||
pleroma: %{notification_settings: ^notification_settings},
|
||||
source: %{privacy: ^privacy}
|
||||
} = AccountView.render("account.json", %{user: user, for: user})
|
||||
end
|
||||
|
||||
test "Represent a Service(bot) account" do
|
||||
|
|
@ -114,14 +121,17 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do
|
|||
bot: true,
|
||||
source: %{
|
||||
note: "",
|
||||
privacy: "public",
|
||||
sensitive: false
|
||||
sensitive: false,
|
||||
pleroma: %{}
|
||||
},
|
||||
pleroma: %{
|
||||
confirmation_pending: false,
|
||||
tags: [],
|
||||
is_admin: false,
|
||||
is_moderator: false,
|
||||
hide_favorites: true,
|
||||
hide_followers: false,
|
||||
hide_follows: false,
|
||||
relationship: %{}
|
||||
}
|
||||
}
|
||||
|
|
@ -200,14 +210,17 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do
|
|||
bot: true,
|
||||
source: %{
|
||||
note: "",
|
||||
privacy: "public",
|
||||
sensitive: false
|
||||
sensitive: false,
|
||||
pleroma: %{}
|
||||
},
|
||||
pleroma: %{
|
||||
confirmation_pending: false,
|
||||
tags: [],
|
||||
is_admin: false,
|
||||
is_moderator: false,
|
||||
hide_favorites: true,
|
||||
hide_followers: false,
|
||||
hide_follows: false,
|
||||
relationship: %{
|
||||
id: to_string(user.id),
|
||||
following: false,
|
||||
|
|
|
|||
|
|
@ -1022,7 +1022,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
|
|||
user2 = insert(:user)
|
||||
user3 = insert(:user)
|
||||
CommonAPI.favorite(activity.id, user2)
|
||||
{:ok, user2} = User.bookmark(user2, activity.data["object"]["id"])
|
||||
{:ok, _bookmark} = Pleroma.Bookmark.create(user2.id, activity.id)
|
||||
{:ok, reblog_activity1, _object} = CommonAPI.repeat(activity.id, user1)
|
||||
{:ok, _, _object} = CommonAPI.repeat(activity.id, user2)
|
||||
|
||||
|
|
@ -2214,6 +2214,66 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
|
|||
assert user["locked"] == true
|
||||
end
|
||||
|
||||
test "updates the user's hide_followers status", %{conn: conn} do
|
||||
user = insert(:user)
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> assign(:user, user)
|
||||
|> patch("/api/v1/accounts/update_credentials", %{hide_followers: "true"})
|
||||
|
||||
assert user = json_response(conn, 200)
|
||||
assert user["pleroma"]["hide_followers"] == true
|
||||
end
|
||||
|
||||
test "updates the user's hide_follows status", %{conn: conn} do
|
||||
user = insert(:user)
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> assign(:user, user)
|
||||
|> patch("/api/v1/accounts/update_credentials", %{hide_follows: "true"})
|
||||
|
||||
assert user = json_response(conn, 200)
|
||||
assert user["pleroma"]["hide_follows"] == true
|
||||
end
|
||||
|
||||
test "updates the user's hide_favorites status", %{conn: conn} do
|
||||
user = insert(:user)
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> assign(:user, user)
|
||||
|> patch("/api/v1/accounts/update_credentials", %{hide_favorites: "true"})
|
||||
|
||||
assert user = json_response(conn, 200)
|
||||
assert user["pleroma"]["hide_favorites"] == true
|
||||
end
|
||||
|
||||
test "updates the user's show_role status", %{conn: conn} do
|
||||
user = insert(:user)
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> assign(:user, user)
|
||||
|> patch("/api/v1/accounts/update_credentials", %{show_role: "false"})
|
||||
|
||||
assert user = json_response(conn, 200)
|
||||
assert user["source"]["pleroma"]["show_role"] == false
|
||||
end
|
||||
|
||||
test "updates the user's no_rich_text status", %{conn: conn} do
|
||||
user = insert(:user)
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> assign(:user, user)
|
||||
|> patch("/api/v1/accounts/update_credentials", %{no_rich_text: "true"})
|
||||
|
||||
assert user = json_response(conn, 200)
|
||||
assert user["source"]["pleroma"]["no_rich_text"] == true
|
||||
end
|
||||
|
||||
test "updates the user's name", %{conn: conn} do
|
||||
user = insert(:user)
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
|
|||
use Pleroma.DataCase
|
||||
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.Bookmark
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.User
|
||||
|
|
@ -153,6 +154,25 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
|
|||
assert status.muted == true
|
||||
end
|
||||
|
||||
test "tells if the status is bookmarked" do
|
||||
user = insert(:user)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(user, %{"status" => "Cute girls doing cute things"})
|
||||
status = StatusView.render("status.json", %{activity: activity})
|
||||
|
||||
assert status.bookmarked == false
|
||||
|
||||
status = StatusView.render("status.json", %{activity: activity, for: user})
|
||||
|
||||
assert status.bookmarked == false
|
||||
|
||||
{:ok, _bookmark} = Bookmark.create(user.id, activity.id)
|
||||
|
||||
status = StatusView.render("status.json", %{activity: activity, for: user})
|
||||
|
||||
assert status.bookmarked == true
|
||||
end
|
||||
|
||||
test "a reply" do
|
||||
note = insert(:note_activity)
|
||||
user = insert(:user)
|
||||
|
|
|
|||
|
|
@ -89,17 +89,11 @@ defmodule Pleroma.Web.TwitterAPI.UserViewTest do
|
|||
"following" => false,
|
||||
"follows_you" => false,
|
||||
"statusnet_blocking" => false,
|
||||
"rights" => %{
|
||||
"delete_others_notice" => false,
|
||||
"admin" => false
|
||||
},
|
||||
"statusnet_profile_url" => user.ap_id,
|
||||
"cover_photo" => banner,
|
||||
"background_image" => nil,
|
||||
"is_local" => true,
|
||||
"locked" => false,
|
||||
"default_scope" => "public",
|
||||
"no_rich_text" => false,
|
||||
"hide_follows" => false,
|
||||
"hide_followers" => false,
|
||||
"fields" => [],
|
||||
|
|
@ -112,6 +106,15 @@ defmodule Pleroma.Web.TwitterAPI.UserViewTest do
|
|||
assert represented == UserView.render("show.json", %{user: user})
|
||||
end
|
||||
|
||||
test "User exposes settings for themselves and only for themselves", %{user: user} do
|
||||
as_user = UserView.render("show.json", %{user: user, for: user})
|
||||
assert as_user["default_scope"] == user.info.default_scope
|
||||
assert as_user["no_rich_text"] == user.info.no_rich_text
|
||||
as_stranger = UserView.render("show.json", %{user: user})
|
||||
refute as_stranger["default_scope"]
|
||||
refute as_stranger["no_rich_text"]
|
||||
end
|
||||
|
||||
test "A user for a given other follower", %{user: user} do
|
||||
follower = insert(:user, %{following: [User.ap_followers(user)]})
|
||||
{:ok, user} = User.update_follower_count(user)
|
||||
|
|
@ -137,17 +140,11 @@ defmodule Pleroma.Web.TwitterAPI.UserViewTest do
|
|||
"following" => true,
|
||||
"follows_you" => false,
|
||||
"statusnet_blocking" => false,
|
||||
"rights" => %{
|
||||
"delete_others_notice" => false,
|
||||
"admin" => false
|
||||
},
|
||||
"statusnet_profile_url" => user.ap_id,
|
||||
"cover_photo" => banner,
|
||||
"background_image" => nil,
|
||||
"is_local" => true,
|
||||
"locked" => false,
|
||||
"default_scope" => "public",
|
||||
"no_rich_text" => false,
|
||||
"hide_follows" => false,
|
||||
"hide_followers" => false,
|
||||
"fields" => [],
|
||||
|
|
@ -186,17 +183,11 @@ defmodule Pleroma.Web.TwitterAPI.UserViewTest do
|
|||
"following" => false,
|
||||
"follows_you" => true,
|
||||
"statusnet_blocking" => false,
|
||||
"rights" => %{
|
||||
"delete_others_notice" => false,
|
||||
"admin" => false
|
||||
},
|
||||
"statusnet_profile_url" => follower.ap_id,
|
||||
"cover_photo" => banner,
|
||||
"background_image" => nil,
|
||||
"is_local" => true,
|
||||
"locked" => false,
|
||||
"default_scope" => "public",
|
||||
"no_rich_text" => false,
|
||||
"hide_follows" => false,
|
||||
"hide_followers" => false,
|
||||
"fields" => [],
|
||||
|
|
@ -272,17 +263,11 @@ defmodule Pleroma.Web.TwitterAPI.UserViewTest do
|
|||
"following" => false,
|
||||
"follows_you" => false,
|
||||
"statusnet_blocking" => true,
|
||||
"rights" => %{
|
||||
"delete_others_notice" => false,
|
||||
"admin" => false
|
||||
},
|
||||
"statusnet_profile_url" => user.ap_id,
|
||||
"cover_photo" => banner,
|
||||
"background_image" => nil,
|
||||
"is_local" => true,
|
||||
"locked" => false,
|
||||
"default_scope" => "public",
|
||||
"no_rich_text" => false,
|
||||
"hide_follows" => false,
|
||||
"hide_followers" => false,
|
||||
"fields" => [],
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue