forked from potsda.mn/mobilizon
Merge remote-tracking branch 'origin/main'
This commit is contained in:
commit
81ae56d850
|
@ -33,7 +33,7 @@
|
|||
# If you want to enforce a style guide and need a more traditional linting
|
||||
# experience, you can change `strict` to `true` below:
|
||||
#
|
||||
strict: false,
|
||||
strict: true,
|
||||
#
|
||||
# If you want to use uncolored output by default, you can change `color`
|
||||
# to `false` below:
|
||||
|
@ -160,6 +160,7 @@
|
|||
#
|
||||
{Credo.Check.Warning.LazyLogging, false},
|
||||
{Credo.Check.Refactor.MapInto, false},
|
||||
{Credo.Check.Warning.MissedMetadataKeyInLoggerConfig, false}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
|
16
Makefile
16
Makefile
|
@ -4,25 +4,25 @@ init:
|
|||
|
||||
setup: stop
|
||||
@bash docker/message.sh "Compiling everything"
|
||||
docker-compose run --rm api bash -c 'mix deps.get; npm ci; npm run build:pictures; mix ecto.create; mix ecto.migrate'
|
||||
docker compose run --rm api bash -c 'mix deps.get; npm ci; npm run build:pictures; mix ecto.create; mix ecto.migrate'
|
||||
migrate:
|
||||
docker-compose run --rm api mix ecto.migrate
|
||||
docker compose run --rm api mix ecto.migrate
|
||||
logs:
|
||||
docker-compose logs -f
|
||||
docker compose logs -f
|
||||
start: stop
|
||||
@bash docker/message.sh "Starting Mobilizon with Docker"
|
||||
docker-compose up -d api
|
||||
docker compose up -d api
|
||||
@bash docker/message.sh "Docker server started"
|
||||
stop:
|
||||
@bash docker/message.sh "Stopping Mobilizon"
|
||||
docker-compose down
|
||||
docker compose down
|
||||
@bash docker/message.sh "Mobilizon is stopped"
|
||||
test: stop
|
||||
@bash docker/message.sh "Running tests"
|
||||
docker-compose -f docker-compose.yml -f docker-compose.test.yml run api mix prepare_test
|
||||
docker-compose -f docker-compose.yml -f docker-compose.test.yml run api mix test $(only)
|
||||
docker compose -f docker compose.yml -f docker compose.test.yml run api mix prepare_test
|
||||
docker compose -f docker compose.yml -f docker compose.test.yml run api mix test $(only)
|
||||
@bash docker/message.sh "Done running tests"
|
||||
format:
|
||||
docker-compose run --rm api bash -c "mix format && mix credo --strict"
|
||||
docker compose run --rm api bash -c "mix format && mix credo --strict"
|
||||
@bash docker/message.sh "Code is now ready to commit :)"
|
||||
target: init
|
||||
|
|
|
@ -25,7 +25,7 @@ defmodule Mobilizon.Federation.ActivityPub.Actions.Invite do
|
|||
) do
|
||||
Logger.debug("Handling #{actor_url} invite to #{group_url} sent to #{target_actor_url}")
|
||||
|
||||
if is_able_to_invite?(actor, group) do
|
||||
if able_to_invite?(actor, group) do
|
||||
with {:ok, %Member{url: member_url} = member} <-
|
||||
Actors.create_member(%{
|
||||
parent_id: group_id,
|
||||
|
@ -64,8 +64,8 @@ defmodule Mobilizon.Federation.ActivityPub.Actions.Invite do
|
|||
end
|
||||
end
|
||||
|
||||
@spec is_able_to_invite?(Actor.t(), Actor.t()) :: boolean
|
||||
defp is_able_to_invite?(%Actor{domain: actor_domain, id: actor_id}, %Actor{
|
||||
@spec able_to_invite?(Actor.t(), Actor.t()) :: boolean
|
||||
defp able_to_invite?(%Actor{domain: actor_domain, id: actor_id}, %Actor{
|
||||
domain: group_domain,
|
||||
id: group_id
|
||||
}) do
|
||||
|
@ -76,7 +76,7 @@ defmodule Mobilizon.Federation.ActivityPub.Actions.Invite do
|
|||
# If local group, we'll send the invite
|
||||
case Actors.get_member(actor_id, group_id) do
|
||||
{:ok, %Member{} = admin_member} ->
|
||||
Member.is_administrator(admin_member)
|
||||
Member.administrator?(admin_member)
|
||||
|
||||
_ ->
|
||||
false
|
||||
|
|
|
@ -34,7 +34,7 @@ defmodule Mobilizon.Federation.ActivityPub.Actions.Leave do
|
|||
local,
|
||||
additional
|
||||
) do
|
||||
if Participant.is_not_only_organizer(event_id, actor_id) do
|
||||
if Participant.not_only_organizer?(event_id, actor_id) do
|
||||
{:error, :is_only_organizer}
|
||||
else
|
||||
case Mobilizon.Events.get_participant(
|
||||
|
@ -83,7 +83,7 @@ defmodule Mobilizon.Federation.ActivityPub.Actions.Leave do
|
|||
case Actors.get_member(actor_id, group_id) do
|
||||
{:ok, %Member{id: member_id} = member} ->
|
||||
if Map.get(additional, :force_member_removal, false) || group_domain != actor_domain ||
|
||||
!Actors.is_only_administrator?(member_id, group_id) do
|
||||
!Actors.only_administrator?(member_id, group_id) do
|
||||
with {:ok, %Member{} = member} <- Actors.delete_member(member) do
|
||||
Mobilizon.Service.Activity.Member.insert_activity(member, subject: "member_quit")
|
||||
|
||||
|
|
|
@ -44,13 +44,13 @@ defmodule Mobilizon.Federation.ActivityPub.Permission do
|
|||
) do
|
||||
case object |> Ownable.permissions() |> get_in([:create]) do
|
||||
:member ->
|
||||
Actors.is_member?(actor_id, group_id)
|
||||
Actors.member?(actor_id, group_id)
|
||||
|
||||
:moderator ->
|
||||
Actors.is_moderator?(actor_id, group_id)
|
||||
Actors.moderator?(actor_id, group_id)
|
||||
|
||||
:administrator ->
|
||||
Actors.is_administrator?(actor_id, group_id)
|
||||
Actors.administrator?(actor_id, group_id)
|
||||
|
||||
_ ->
|
||||
false
|
||||
|
@ -122,21 +122,21 @@ defmodule Mobilizon.Federation.ActivityPub.Permission do
|
|||
"Checking if activity actor #{actor_url} is a moderator from group from #{object.url}"
|
||||
)
|
||||
|
||||
Actors.is_moderator?(actor_id, group_id)
|
||||
Actors.moderator?(actor_id, group_id)
|
||||
|
||||
:administrator ->
|
||||
Logger.debug(
|
||||
"Checking if activity actor #{actor_url} is an administrator from group from #{object.url}"
|
||||
)
|
||||
|
||||
Actors.is_administrator?(actor_id, group_id)
|
||||
Actors.administrator?(actor_id, group_id)
|
||||
|
||||
_ ->
|
||||
Logger.debug(
|
||||
"Checking if activity actor #{actor_url} is a member from group from #{object.url}"
|
||||
)
|
||||
|
||||
Actors.is_member?(actor_id, group_id)
|
||||
Actors.member?(actor_id, group_id)
|
||||
end
|
||||
|
||||
_ ->
|
||||
|
|
|
@ -21,10 +21,10 @@ defmodule Mobilizon.Federation.ActivityPub.Publisher do
|
|||
Logger.debug("Publishing an activity")
|
||||
Logger.debug(inspect(activity, pretty: true))
|
||||
|
||||
public = Visibility.is_public?(activity)
|
||||
public = Visibility.public?(activity)
|
||||
Logger.debug("is public ? #{public}")
|
||||
|
||||
if public && is_create_activity?(activity) && Config.get([:instance, :allow_relay]) do
|
||||
if public && create_activity?(activity) && Config.get([:instance, :allow_relay]) do
|
||||
Logger.info(fn -> "Relaying #{activity.data["id"]} out" end)
|
||||
|
||||
Relay.publish(activity)
|
||||
|
@ -125,9 +125,9 @@ defmodule Mobilizon.Federation.ActivityPub.Publisher do
|
|||
end)
|
||||
end
|
||||
|
||||
@spec is_create_activity?(Activity.t()) :: boolean
|
||||
defp is_create_activity?(%Activity{data: %{"type" => "Create"}}), do: true
|
||||
defp is_create_activity?(_), do: false
|
||||
@spec create_activity?(Activity.t()) :: boolean
|
||||
defp create_activity?(%Activity{data: %{"type" => "Create"}}), do: true
|
||||
defp create_activity?(_), do: false
|
||||
|
||||
@spec convert_members_in_recipients(list(String.t())) :: {list(String.t()), list(Actor.t())}
|
||||
defp convert_members_in_recipients(recipients) do
|
||||
|
|
|
@ -285,7 +285,7 @@ defmodule Mobilizon.Federation.ActivityPub.Transmogrifier do
|
|||
object_data when is_map(object_data) <-
|
||||
object |> Converter.Resource.as_to_model_data(),
|
||||
{:member, true} <-
|
||||
{:member, Actors.is_member?(object_data.creator_id, object_data.actor_id)},
|
||||
{:member, Actors.member?(object_data.creator_id, object_data.actor_id)},
|
||||
{:ok, %Activity{} = activity, %Resource{} = resource} <-
|
||||
Actions.Create.create(:resource, object_data, false) do
|
||||
{:ok, activity, resource}
|
||||
|
@ -1005,14 +1005,14 @@ defmodule Mobilizon.Federation.ActivityPub.Transmogrifier do
|
|||
end
|
||||
|
||||
# Comment initiates a whole discussion only if it has full title
|
||||
@spec is_data_for_comment_or_discussion?(map()) :: boolean()
|
||||
defp is_data_for_comment_or_discussion?(object_data) do
|
||||
is_data_a_discussion_initialization?(object_data) and
|
||||
@spec data_for_comment_or_discussion?(map()) :: boolean()
|
||||
defp data_for_comment_or_discussion?(object_data) do
|
||||
data_a_discussion_initialization?(object_data) and
|
||||
is_nil(object_data.discussion_id)
|
||||
end
|
||||
|
||||
# Comment initiates a whole discussion only if it has full title
|
||||
defp is_data_a_discussion_initialization?(object_data) do
|
||||
defp data_a_discussion_initialization?(object_data) do
|
||||
not Map.has_key?(object_data, :title) or
|
||||
is_nil(object_data.title) or object_data.title == ""
|
||||
end
|
||||
|
@ -1034,7 +1034,7 @@ defmodule Mobilizon.Federation.ActivityPub.Transmogrifier do
|
|||
@spec transform_object_data_for_discussion(map()) :: map()
|
||||
defp transform_object_data_for_discussion(object_data) do
|
||||
# Basic comment
|
||||
if is_data_a_discussion_initialization?(object_data) do
|
||||
if data_a_discussion_initialization?(object_data) do
|
||||
object_data
|
||||
else
|
||||
# Conversation
|
||||
|
@ -1138,8 +1138,8 @@ defmodule Mobilizon.Federation.ActivityPub.Transmogrifier do
|
|||
end
|
||||
end
|
||||
|
||||
defp is_group_object_gone(object_id) do
|
||||
Logger.debug("is_group_object_gone #{object_id}")
|
||||
defp group_object_gone_check(object_id) do
|
||||
Logger.debug("Checking if group object #{object_id} is gone")
|
||||
|
||||
case ActivityPub.fetch_object_from_url(object_id, force: true) do
|
||||
# comments are just emptied
|
||||
|
@ -1163,14 +1163,10 @@ defmodule Mobilizon.Federation.ActivityPub.Transmogrifier do
|
|||
end
|
||||
end
|
||||
|
||||
# Before 1.0.4 the object of a "Remove" activity was an actor's URL
|
||||
# instead of the member's URL.
|
||||
# TODO: Remove in 1.2
|
||||
@spec get_remove_object(map() | String.t()) :: {:ok, integer()}
|
||||
defp get_remove_object(object) do
|
||||
case object |> Utils.get_url() |> ActivityPub.fetch_object_from_url() do
|
||||
{:ok, %Member{actor: %Actor{id: person_id}}} -> {:ok, person_id}
|
||||
{:ok, %Actor{id: person_id}} -> {:ok, person_id}
|
||||
_ -> {:error, :remove_object_not_found}
|
||||
end
|
||||
end
|
||||
|
@ -1196,7 +1192,7 @@ defmodule Mobilizon.Federation.ActivityPub.Transmogrifier do
|
|||
@spec create_comment_or_discussion(map()) ::
|
||||
{:ok, Activity.t(), struct()} | {:error, atom() | Ecto.Changeset.t()}
|
||||
defp create_comment_or_discussion(object_data) do
|
||||
if is_data_for_comment_or_discussion?(object_data) do
|
||||
if data_for_comment_or_discussion?(object_data) do
|
||||
Logger.debug("Chosing to create a regular comment")
|
||||
Actions.Create.create(:comment, object_data, false)
|
||||
else
|
||||
|
@ -1248,7 +1244,7 @@ defmodule Mobilizon.Federation.ActivityPub.Transmogrifier do
|
|||
end
|
||||
|
||||
defp handle_group_being_gone(actor, actor_url, object_id) do
|
||||
case is_group_object_gone(object_id) do
|
||||
case group_object_gone_check(object_id) do
|
||||
# The group object is no longer there, we can remove the element
|
||||
{:ok, entity} ->
|
||||
if Utils.origin_check_from_id?(actor_url, object_id) ||
|
||||
|
|
|
@ -93,7 +93,7 @@ defmodule Mobilizon.Federation.ActivityPub.Types.Members do
|
|||
atom()
|
||||
) :: boolean
|
||||
defp check_admins_left?(member_id, group_id, current_role, updated_role) do
|
||||
Actors.is_only_administrator?(member_id, group_id) && current_role == :administrator &&
|
||||
Actors.only_administrator?(member_id, group_id) && current_role == :administrator &&
|
||||
updated_role != :administrator
|
||||
end
|
||||
end
|
||||
|
|
|
@ -14,17 +14,17 @@ defmodule Mobilizon.Federation.ActivityPub.Visibility do
|
|||
|
||||
@public "https://www.w3.org/ns/activitystreams#Public"
|
||||
|
||||
@spec is_public?(Activity.t() | map()) :: boolean()
|
||||
def is_public?(%{data: %{"type" => "Tombstone"}}), do: false
|
||||
def is_public?(%{data: data}), do: is_public?(data)
|
||||
def is_public?(%Activity{data: data}), do: is_public?(data)
|
||||
@spec public?(Activity.t() | map()) :: boolean()
|
||||
def public?(%{data: %{"type" => "Tombstone"}}), do: false
|
||||
def public?(%{data: data}), do: public?(data)
|
||||
def public?(%Activity{data: data}), do: public?(data)
|
||||
|
||||
def is_public?(data) when is_map(data) do
|
||||
def public?(data) when is_map(data) do
|
||||
@public in make_list(Map.get(data, "to", []))
|
||||
end
|
||||
|
||||
def is_public?(%Comment{deleted_at: deleted_at}), do: !is_nil(deleted_at)
|
||||
def is_public?(err), do: raise(ArgumentError, message: "Invalid argument #{inspect(err)}")
|
||||
def public?(%Comment{deleted_at: deleted_at}), do: !is_nil(deleted_at)
|
||||
def public?(err), do: raise(ArgumentError, message: "Invalid argument #{inspect(err)}")
|
||||
|
||||
defp make_list(data) when is_list(data), do: data
|
||||
defp make_list(data), do: [data]
|
||||
|
|
|
@ -76,14 +76,13 @@ defmodule Mobilizon.Federation.ActivityStream.Converter.Actor do
|
|||
def as_to_model_data(_), do: {:error, :actor_not_allowed_type}
|
||||
|
||||
defp add_endpoints_to_model(actor, data) do
|
||||
# TODO: Remove fallbacks in 3.0
|
||||
endpoints = %{
|
||||
members_url: get_in(data, ["endpoints", "members"]) || data["members"],
|
||||
resources_url: get_in(data, ["endpoints", "resources"]) || data["resources"],
|
||||
todos_url: get_in(data, ["endpoints", "todos"]) || data["todos"],
|
||||
events_url: get_in(data, ["endpoints", "events"]) || data["events"],
|
||||
posts_url: get_in(data, ["endpoints", "posts"]) || data["posts"],
|
||||
discussions_url: get_in(data, ["endpoints", "discussions"]) || data["discussions"],
|
||||
members_url: get_in(data, ["endpoints", "members"]),
|
||||
resources_url: get_in(data, ["endpoints", "resources"]),
|
||||
todos_url: get_in(data, ["endpoints", "todos"]),
|
||||
events_url: get_in(data, ["endpoints", "events"]),
|
||||
posts_url: get_in(data, ["endpoints", "posts"]),
|
||||
discussions_url: get_in(data, ["endpoints", "discussions"]),
|
||||
shared_inbox_url: data["endpoints"]["sharedInbox"]
|
||||
}
|
||||
|
||||
|
|
|
@ -62,7 +62,7 @@ defmodule Mobilizon.Federation.ActivityStream.Converter.Comment do
|
|||
tags: fetch_tags(tag_object),
|
||||
mentions: fetch_mentions(tag_object),
|
||||
local: is_nil(actor_domain),
|
||||
visibility: if(Visibility.is_public?(object), do: :public, else: :private),
|
||||
visibility: if(Visibility.public?(object), do: :public, else: :private),
|
||||
published_at: object["published"],
|
||||
is_announcement: Map.get(object, "isAnnouncement", false)
|
||||
}
|
||||
|
|
|
@ -77,7 +77,7 @@ defmodule Mobilizon.Federation.ActivityStream.Converter.Event do
|
|||
category: Categories.get_category(object["category"]),
|
||||
visibility: visibility,
|
||||
join_options: Map.get(object, "joinMode", "free"),
|
||||
local: is_local?(object["id"]),
|
||||
local: local?(object["id"]),
|
||||
external_participation_url: object["externalParticipationUrl"],
|
||||
options: options,
|
||||
metadata: metadata,
|
||||
|
@ -305,8 +305,8 @@ defmodule Mobilizon.Federation.ActivityStream.Converter.Event do
|
|||
)
|
||||
end
|
||||
|
||||
@spec is_local?(String.t()) :: boolean()
|
||||
defp is_local?(url) do
|
||||
@spec local?(String.t()) :: boolean()
|
||||
defp local?(url) do
|
||||
%URI{host: url_domain} = URI.parse(url)
|
||||
%URI{host: local_domain} = URI.parse(Endpoint.url())
|
||||
url_domain == local_domain
|
||||
|
|
|
@ -5,7 +5,7 @@ defmodule Mobilizon.Federation.NodeInfo do
|
|||
|
||||
alias Mobilizon.Service.HTTP.WebfingerClient
|
||||
require Logger
|
||||
import Mobilizon.Service.HTTP.Utils, only: [is_content_type?: 2]
|
||||
import Mobilizon.Service.HTTP.Utils, only: [content_type_matches?: 2]
|
||||
|
||||
@application_uri "https://www.w3.org/ns/activitystreams#Application"
|
||||
@nodeinfo_rel_2_0 "http://nodeinfo.diaspora.software/ns/schema/2.0"
|
||||
|
@ -110,7 +110,7 @@ defmodule Mobilizon.Federation.NodeInfo do
|
|||
{:ok, String.t()} | {:error, :bad_content_type | :body_not_json}
|
||||
defp validate_json_response(body, headers) do
|
||||
cond do
|
||||
!is_content_type?(headers, "application/json") ->
|
||||
!content_type_matches?(headers, "application/json") ->
|
||||
{:error, :bad_content_type}
|
||||
|
||||
!is_map(body) ->
|
||||
|
|
|
@ -25,8 +25,8 @@ defmodule Mobilizon.GraphQL.API.Search do
|
|||
|
||||
cond do
|
||||
# Some URLs could be domain.tld/@username, so keep this condition above
|
||||
# the `is_handle` function
|
||||
is_url(term) ->
|
||||
# the `handle?` function
|
||||
url?(term) ->
|
||||
# skip, if it's not an actor
|
||||
case process_from_url(term) do
|
||||
%Page{total: _total, elements: [%Actor{} = _actor]} = page ->
|
||||
|
@ -36,11 +36,11 @@ defmodule Mobilizon.GraphQL.API.Search do
|
|||
{:ok, %{total: 0, elements: []}}
|
||||
end
|
||||
|
||||
is_handle(term) ->
|
||||
handle?(term) ->
|
||||
{:ok, process_from_username(term)}
|
||||
|
||||
true ->
|
||||
if is_global_search(args) do
|
||||
if global_search?(args) do
|
||||
service = GlobalSearch.service()
|
||||
|
||||
{:ok, service.search_groups(Keyword.new(args, fn {k, v} -> {k, v} end))}
|
||||
|
@ -75,7 +75,7 @@ defmodule Mobilizon.GraphQL.API.Search do
|
|||
def search_events(%{term: term} = args, page \\ 1, limit \\ 10) do
|
||||
term = String.trim(term)
|
||||
|
||||
if is_url(term) do
|
||||
if url?(term) do
|
||||
# skip, if it's not an event
|
||||
case process_from_url(term) do
|
||||
%Page{total: _total, elements: [%Event{} = event]} = page ->
|
||||
|
@ -89,7 +89,7 @@ defmodule Mobilizon.GraphQL.API.Search do
|
|||
{:ok, %{total: 0, elements: []}}
|
||||
end
|
||||
else
|
||||
if is_global_search(args) do
|
||||
if global_search?(args) do
|
||||
service = GlobalSearch.service()
|
||||
|
||||
{:ok, service.search_events(Keyword.new(args, fn {k, v} -> {k, v} end))}
|
||||
|
@ -140,17 +140,17 @@ defmodule Mobilizon.GraphQL.API.Search do
|
|||
end
|
||||
end
|
||||
|
||||
@spec is_url(String.t()) :: boolean
|
||||
defp is_url(search), do: String.starts_with?(search, ["http://", "https://"])
|
||||
@spec url?(String.t()) :: boolean
|
||||
defp url?(search), do: String.starts_with?(search, ["http://", "https://"])
|
||||
|
||||
@spec is_handle(String.t()) :: boolean
|
||||
defp is_handle(search), do: String.match?(search, ~r/@/)
|
||||
@spec handle?(String.t()) :: boolean
|
||||
defp handle?(search), do: String.match?(search, ~r/@/)
|
||||
|
||||
defp is_global_search(%{search_target: :global}) do
|
||||
defp global_search?(%{search_target: :global}) do
|
||||
global_search_enabled?()
|
||||
end
|
||||
|
||||
defp is_global_search(_), do: global_search_enabled?() && global_search_default?()
|
||||
defp global_search?(_), do: global_search_enabled?() && global_search_default?()
|
||||
|
||||
defp global_search_enabled? do
|
||||
Application.get_env(:mobilizon, :search) |> get_in([:global]) |> get_in([:is_enabled])
|
||||
|
|
|
@ -68,6 +68,6 @@ defmodule Mobilizon.GraphQL.API.Utils do
|
|||
|
||||
@spec check_actor_owns_media?(integer() | String.t(), integer() | String.t()) :: boolean()
|
||||
defp check_actor_owns_media?(actor_id, media_actor_id) do
|
||||
actor_id == media_actor_id || Mobilizon.Actors.is_member?(media_actor_id, actor_id)
|
||||
actor_id == media_actor_id || Mobilizon.Actors.member?(media_actor_id, actor_id)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -5,8 +5,8 @@ defmodule Mobilizon.GraphQL.Error do
|
|||
|
||||
require Logger
|
||||
alias __MODULE__
|
||||
alias Mobilizon.Web.Gettext, as: GettextBackend
|
||||
import Mobilizon.Web.Gettext, only: [dgettext: 2]
|
||||
import Mobilizon.Storage.Ecto, only: [convert_ecto_errors: 1]
|
||||
|
||||
@type t :: %{code: atom(), message: String.t(), status_code: pos_integer(), field: atom()}
|
||||
|
||||
|
@ -64,7 +64,7 @@ defmodule Mobilizon.GraphQL.Error do
|
|||
|
||||
defp handle(%Ecto.Changeset{} = changeset) do
|
||||
changeset
|
||||
|> Ecto.Changeset.traverse_errors(&translate_error/1)
|
||||
|> convert_ecto_errors()
|
||||
|> Enum.map(fn {k, v} ->
|
||||
%Error{
|
||||
code: :validation,
|
||||
|
@ -126,27 +126,4 @@ defmodule Mobilizon.GraphQL.Error do
|
|||
Logger.warning("Unhandled error code: #{inspect(code)}")
|
||||
{422, to_string(code)}
|
||||
end
|
||||
|
||||
# Translates an error message using gettext.
|
||||
defp translate_error({msg, opts}) do
|
||||
# Because error messages were defined within Ecto, we must
|
||||
# call the Gettext module passing our Gettext backend. We
|
||||
# also use the "errors" domain as translations are placed
|
||||
# in the errors.po file.
|
||||
# Ecto will pass the :count keyword if the error message is
|
||||
# meant to be pluralized.
|
||||
# On your own code and templates, depending on whether you
|
||||
# need the message to be pluralized or not, this could be
|
||||
# written simply as:
|
||||
#
|
||||
# dngettext "errors", "1 file", "%{count} files", count
|
||||
# dgettext "errors", "is invalid"
|
||||
#
|
||||
|
||||
if count = opts[:count] do
|
||||
Gettext.dngettext(GettextBackend, "errors", msg, msg, count, opts)
|
||||
else
|
||||
Gettext.dgettext(GettextBackend, "errors", msg, opts)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -18,7 +18,7 @@ defmodule Mobilizon.GraphQL.Resolvers.Activity do
|
|||
def group_activity(%Actor{type: :Group, id: group_id}, %{page: page, limit: limit} = args, %{
|
||||
context: %{current_user: %User{role: role}, current_actor: %Actor{id: actor_id}}
|
||||
}) do
|
||||
if Actors.is_member?(actor_id, group_id) or is_moderator(role) do
|
||||
if Actors.member?(actor_id, group_id) or is_moderator(role) do
|
||||
%Page{total: total, elements: elements} =
|
||||
Activities.list_group_activities_for_member(
|
||||
group_id,
|
||||
|
|
|
@ -26,7 +26,7 @@ defmodule Mobilizon.GraphQL.Resolvers.Conversation do
|
|||
}
|
||||
)
|
||||
when not is_nil(attributed_to_id) do
|
||||
if Actors.is_member?(actor_id, attributed_to_id) do
|
||||
if Actors.member?(actor_id, attributed_to_id) do
|
||||
{:ok,
|
||||
event_id
|
||||
|> Conversations.find_conversations_for_event(attributed_to_id, page, limit)
|
||||
|
@ -103,7 +103,7 @@ defmodule Mobilizon.GraphQL.Resolvers.Conversation do
|
|||
{:error, :not_found}
|
||||
|
||||
%ConversationParticipant{actor_id: actor_id} = conversation_participant ->
|
||||
if actor_id == performing_actor_id or Actors.is_member?(performing_actor_id, actor_id) do
|
||||
if actor_id == performing_actor_id or Actors.member?(performing_actor_id, actor_id) do
|
||||
{:ok, conversation_participant_to_view(conversation_participant)}
|
||||
else
|
||||
{:error, :not_found}
|
||||
|
@ -121,7 +121,7 @@ defmodule Mobilizon.GraphQL.Resolvers.Conversation do
|
|||
}
|
||||
) do
|
||||
if conversation_actor_id == performing_actor_id or
|
||||
Actors.is_member?(performing_actor_id, conversation_actor_id) do
|
||||
Actors.member?(performing_actor_id, conversation_actor_id) do
|
||||
{:ok,
|
||||
Mobilizon.Discussions.get_comments_in_reply_to_comment_id(origin_comment_id, page, limit)}
|
||||
else
|
||||
|
@ -184,7 +184,7 @@ defmodule Mobilizon.GraphQL.Resolvers.Conversation do
|
|||
{:valid_actor, true} <-
|
||||
{:valid_actor,
|
||||
actor_id == current_actor_id or
|
||||
Actors.is_member?(current_actor_id, actor_id)},
|
||||
Actors.member?(current_actor_id, actor_id)},
|
||||
{:ok, %ConversationParticipant{} = conversation_participant} <-
|
||||
Conversations.update_conversation_participant(conversation_participant, %{
|
||||
unread: !read
|
||||
|
@ -269,7 +269,7 @@ defmodule Mobilizon.GraphQL.Resolvers.Conversation do
|
|||
|
||||
to_string(current_actor_id) in participant_ids or
|
||||
Enum.any?(participant_ids, fn participant_id ->
|
||||
Actors.is_member?(current_actor_id, participant_id) and
|
||||
Actors.member?(current_actor_id, participant_id) and
|
||||
attributed_to_id == participant_id
|
||||
end)
|
||||
end
|
||||
|
|
|
@ -23,7 +23,7 @@ defmodule Mobilizon.GraphQL.Resolvers.Discussion do
|
|||
}
|
||||
}
|
||||
) do
|
||||
with {:member, true} <- {:member, Actors.is_member?(actor_id, group_id)},
|
||||
with {:member, true} <- {:member, Actors.member?(actor_id, group_id)},
|
||||
{:ok, %Actor{type: :Group} = group} <- Actors.get_group_by_actor_id(group_id) do
|
||||
{:ok, Discussions.find_discussions_for_actor(group, page, limit)}
|
||||
else
|
||||
|
@ -45,7 +45,7 @@ defmodule Mobilizon.GraphQL.Resolvers.Discussion do
|
|||
}) do
|
||||
case Discussions.get_discussion(id) do
|
||||
%Discussion{actor_id: actor_id} = discussion ->
|
||||
if Actors.is_member?(creator_id, actor_id) do
|
||||
if Actors.member?(creator_id, actor_id) do
|
||||
{:ok, discussion}
|
||||
else
|
||||
{:error, :unauthorized}
|
||||
|
@ -63,7 +63,7 @@ defmodule Mobilizon.GraphQL.Resolvers.Discussion do
|
|||
}) do
|
||||
with %Discussion{actor_id: actor_id} = discussion <-
|
||||
Discussions.get_discussion_by_slug(slug),
|
||||
{:member, true} <- {:member, Actors.is_member?(creator_id, actor_id)} do
|
||||
{:member, true} <- {:member, Actors.member?(creator_id, actor_id)} do
|
||||
{:ok, discussion}
|
||||
else
|
||||
nil -> {:error, dgettext("errors", "Discussion not found")}
|
||||
|
@ -105,7 +105,7 @@ defmodule Mobilizon.GraphQL.Resolvers.Discussion do
|
|||
}
|
||||
}
|
||||
) do
|
||||
if Actors.is_member?(creator_id, group_id) do
|
||||
if Actors.member?(creator_id, group_id) do
|
||||
case Comments.create_discussion(%{
|
||||
title: title,
|
||||
text: text,
|
||||
|
@ -150,7 +150,7 @@ defmodule Mobilizon.GraphQL.Resolvers.Discussion do
|
|||
}
|
||||
} = _discussion} <-
|
||||
{:no_discussion, Discussions.get_discussion(discussion_id)},
|
||||
{:member, true} <- {:member, Actors.is_member?(creator_id, actor_id)},
|
||||
{:member, true} <- {:member, Actors.member?(creator_id, actor_id)},
|
||||
{:ok, _activity, %Discussion{} = discussion} <-
|
||||
Comments.create_discussion(%{
|
||||
text: text,
|
||||
|
@ -183,7 +183,7 @@ defmodule Mobilizon.GraphQL.Resolvers.Discussion do
|
|||
) do
|
||||
with {:no_discussion, %Discussion{actor_id: actor_id} = discussion} <-
|
||||
{:no_discussion, Discussions.get_discussion(discussion_id)},
|
||||
{:member, true} <- {:member, Actors.is_member?(creator_id, actor_id)},
|
||||
{:member, true} <- {:member, Actors.member?(creator_id, actor_id)},
|
||||
{:ok, _activity, %Discussion{} = discussion} <-
|
||||
Actions.Update.update(
|
||||
discussion,
|
||||
|
@ -213,7 +213,7 @@ defmodule Mobilizon.GraphQL.Resolvers.Discussion do
|
|||
}) do
|
||||
with {:no_discussion, %Discussion{actor_id: actor_id} = discussion} <-
|
||||
{:no_discussion, Discussions.get_discussion(discussion_id)},
|
||||
{:member, true} <- {:member, Actors.is_member?(creator_id, actor_id)},
|
||||
{:member, true} <- {:member, Actors.member?(creator_id, actor_id)},
|
||||
{:ok, _activity, %Discussion{} = discussion} <-
|
||||
Actions.Delete.delete(discussion, actor) do
|
||||
{:ok, discussion}
|
||||
|
|
|
@ -36,7 +36,7 @@ defmodule Mobilizon.GraphQL.Resolvers.Event do
|
|||
when not is_nil(attributed_to_id) do
|
||||
with %Actor{id: group_id} <- Actors.get_actor(attributed_to_id),
|
||||
{:member, true} <-
|
||||
{:member, Actors.is_member?(actor_id, group_id) or is_moderator(user_role)},
|
||||
{:member, Actors.member?(actor_id, group_id) or is_moderator(user_role)},
|
||||
%Actor{} = actor <- Actors.get_actor(organizer_actor_id) do
|
||||
{:ok, actor}
|
||||
else
|
||||
|
@ -176,7 +176,7 @@ defmodule Mobilizon.GraphQL.Resolvers.Event do
|
|||
_args,
|
||||
%{context: %{current_user: %User{id: user_id} = _user}} = _resolution
|
||||
) do
|
||||
if Events.is_user_moderator_for_event?(user_id, event_id) do
|
||||
if Events.user_moderator_for_event?(user_id, event_id) do
|
||||
{:ok,
|
||||
Map.put(
|
||||
stats,
|
||||
|
@ -256,7 +256,7 @@ defmodule Mobilizon.GraphQL.Resolvers.Event do
|
|||
{:can_create_event, true} <- can_create_event(args),
|
||||
{:event_external, true} <- edit_event_external_checker(args),
|
||||
{:organizer_group_member, true} <-
|
||||
{:organizer_group_member, is_organizer_group_member?(args)},
|
||||
{:organizer_group_member, organizer_group_member?(args)},
|
||||
args_with_organizer <-
|
||||
args |> Map.put(:organizer_actor, organizer_actor) |> extract_timezone(user.id),
|
||||
{:askismet, :ham} <-
|
||||
|
@ -447,17 +447,17 @@ defmodule Mobilizon.GraphQL.Resolvers.Event do
|
|||
end
|
||||
end
|
||||
|
||||
@spec is_organizer_group_member?(map()) :: boolean()
|
||||
defp is_organizer_group_member?(%{
|
||||
@spec organizer_group_member?(map()) :: boolean()
|
||||
defp organizer_group_member?(%{
|
||||
attributed_to_id: attributed_to_id,
|
||||
organizer_actor_id: organizer_actor_id
|
||||
})
|
||||
when not is_nil(attributed_to_id) do
|
||||
Actors.is_member?(organizer_actor_id, attributed_to_id) &&
|
||||
Actors.member?(organizer_actor_id, attributed_to_id) &&
|
||||
Permission.can_create_group_object?(organizer_actor_id, attributed_to_id, %Event{})
|
||||
end
|
||||
|
||||
defp is_organizer_group_member?(_), do: true
|
||||
defp organizer_group_member?(_), do: true
|
||||
|
||||
@spec verify_profile_change(map(), Event.t(), User.t(), Actor.t()) :: {:ok, map()}
|
||||
defp verify_profile_change(
|
||||
|
|
|
@ -23,7 +23,7 @@ defmodule Mobilizon.GraphQL.Resolvers.Followers do
|
|||
) do
|
||||
followers = group_followers(group, args)
|
||||
|
||||
if Actors.is_moderator?(actor_id, group_id) or is_moderator(user_role) do
|
||||
if Actors.moderator?(actor_id, group_id) or is_moderator(user_role) do
|
||||
{:ok, followers}
|
||||
else
|
||||
{:ok, %Page{followers | elements: []}}
|
||||
|
@ -48,7 +48,7 @@ defmodule Mobilizon.GraphQL.Resolvers.Followers do
|
|||
with %Follower{target_actor: %Actor{type: :Group, id: group_id}} = follower <-
|
||||
Actors.get_follower(follower_id),
|
||||
{:member, true} <-
|
||||
{:member, Actors.is_moderator?(actor_id, group_id)},
|
||||
{:member, Actors.moderator?(actor_id, group_id)},
|
||||
{:ok, _activity, %Follower{} = follower} <-
|
||||
(if approved do
|
||||
Actions.Accept.accept(:follow, follower)
|
||||
|
|
|
@ -36,7 +36,7 @@ defmodule Mobilizon.GraphQL.Resolvers.Group do
|
|||
) do
|
||||
case ActivityPubActor.find_or_make_group_from_nickname(name) do
|
||||
{:ok, %Actor{id: group_id, suspended: false} = group} ->
|
||||
if Actors.is_member?(actor_id, group_id) do
|
||||
if Actors.member?(actor_id, group_id) do
|
||||
{:ok, group}
|
||||
else
|
||||
find_group(parent, args, nil)
|
||||
|
@ -72,7 +72,7 @@ defmodule Mobilizon.GraphQL.Resolvers.Group do
|
|||
}
|
||||
}) do
|
||||
with %Actor{suspended: false, id: group_id} = group <- Actors.get_actor_with_preload(id),
|
||||
true <- Actors.is_member?(actor_id, group_id) do
|
||||
true <- Actors.member?(actor_id, group_id) do
|
||||
{:ok, group}
|
||||
else
|
||||
_ ->
|
||||
|
@ -215,7 +215,7 @@ defmodule Mobilizon.GraphQL.Resolvers.Group do
|
|||
}
|
||||
}
|
||||
) do
|
||||
if Actors.is_administrator?(updater_actor.id, group_id) do
|
||||
if Actors.administrator?(updater_actor.id, group_id) do
|
||||
args = Map.put(args, :updater_actor, updater_actor)
|
||||
|
||||
case save_attached_pictures(args) do
|
||||
|
@ -265,7 +265,7 @@ defmodule Mobilizon.GraphQL.Resolvers.Group do
|
|||
) do
|
||||
with {:ok, %Actor{} = group} <- Actors.get_group_by_actor_id(group_id),
|
||||
{:ok, %Member{} = member} <- Actors.get_member(actor_id, group.id),
|
||||
{:is_admin, true} <- {:is_admin, Member.is_administrator(member)},
|
||||
{:is_admin, true} <- {:is_admin, Member.administrator?(member)},
|
||||
{:ok, _activity, group} <- Actions.Delete.delete(group, actor, true) do
|
||||
{:ok, %{id: group.id}}
|
||||
else
|
||||
|
@ -448,7 +448,7 @@ defmodule Mobilizon.GraphQL.Resolvers.Group do
|
|||
}
|
||||
}
|
||||
) do
|
||||
if Actors.is_member?(actor_id, group_id) do
|
||||
if Actors.member?(actor_id, group_id) do
|
||||
{:ok,
|
||||
Events.list_organized_events_for_group(
|
||||
group,
|
||||
|
|
|
@ -26,7 +26,7 @@ defmodule Mobilizon.GraphQL.Resolvers.Member do
|
|||
context: %{current_user: %User{role: user_role}, current_actor: %Actor{id: actor_id}}
|
||||
} = _resolution
|
||||
) do
|
||||
if Actors.is_member?(actor_id, group_id) or is_moderator(user_role) do
|
||||
if Actors.member?(actor_id, group_id) or is_moderator(user_role) do
|
||||
roles =
|
||||
case roles do
|
||||
"" ->
|
||||
|
|
|
@ -384,7 +384,7 @@ defmodule Mobilizon.GraphQL.Resolvers.Participant do
|
|||
with {:member, true} <-
|
||||
{:member,
|
||||
to_string(current_actor_id) == to_string(actor_id) or
|
||||
Actors.is_member?(current_actor_id, actor_id)},
|
||||
Actors.member?(current_actor_id, actor_id)},
|
||||
{:ok, _activity, %Conversation{} = conversation} <- Comments.create_conversation(args) do
|
||||
{:ok, conversation_to_view(conversation, Actors.get_actor(actor_id))}
|
||||
else
|
||||
|
|
|
@ -32,7 +32,7 @@ defmodule Mobilizon.GraphQL.Resolvers.Post do
|
|||
}
|
||||
} = _resolution
|
||||
) do
|
||||
if Actors.is_member?(actor_id, group_id) or is_moderator(user_role) do
|
||||
if Actors.member?(actor_id, group_id) or is_moderator(user_role) do
|
||||
%Page{} = page = Posts.get_posts_for_group(group, page, limit)
|
||||
{:ok, page}
|
||||
else
|
||||
|
@ -111,7 +111,7 @@ defmodule Mobilizon.GraphQL.Resolvers.Post do
|
|||
}
|
||||
} = _resolution
|
||||
) do
|
||||
with {:member, true} <- {:member, Actors.is_member?(actor_id, group_id)},
|
||||
with {:member, true} <- {:member, Actors.member?(actor_id, group_id)},
|
||||
%Actor{} = group <- Actors.get_actor(group_id),
|
||||
args <-
|
||||
Map.update(args, :picture, nil, fn picture ->
|
||||
|
@ -160,7 +160,7 @@ defmodule Mobilizon.GraphQL.Resolvers.Post do
|
|||
process_picture(picture, group)
|
||||
end),
|
||||
args <- extract_pictures_from_post_body(args, actor_id),
|
||||
{:member, true} <- {:member, Actors.is_member?(actor_id, group_id)},
|
||||
{:member, true} <- {:member, Actors.member?(actor_id, group_id)},
|
||||
{:ok, _, %Post{} = post} <-
|
||||
Actions.Update.update(post, args, true, %{"actor" => actor_url}) do
|
||||
{:ok, post}
|
||||
|
@ -194,7 +194,7 @@ defmodule Mobilizon.GraphQL.Resolvers.Post do
|
|||
with {:uuid, {:ok, _uuid}} <- {:uuid, Ecto.UUID.cast(post_id)},
|
||||
{:post, %Post{attributed_to: %Actor{id: group_id}} = post} <-
|
||||
{:post, Posts.get_post_with_preloads(post_id)},
|
||||
{:member, true} <- {:member, Actors.is_member?(actor_id, group_id)},
|
||||
{:member, true} <- {:member, Actors.member?(actor_id, group_id)},
|
||||
{:ok, _, %Post{} = post} <-
|
||||
Actions.Delete.delete(post, actor) do
|
||||
{:ok, post}
|
||||
|
|
|
@ -32,7 +32,7 @@ defmodule Mobilizon.GraphQL.Resolvers.Resource do
|
|||
}
|
||||
} = _resolution
|
||||
) do
|
||||
with {:member, true} <- {:member, Actors.is_member?(actor_id, group_id)},
|
||||
with {:member, true} <- {:member, Actors.member?(actor_id, group_id)},
|
||||
%Page{} = page <- Resources.get_resources_for_group(group, page, limit) do
|
||||
{:ok, page}
|
||||
else
|
||||
|
@ -60,7 +60,7 @@ defmodule Mobilizon.GraphQL.Resolvers.Resource do
|
|||
}
|
||||
} = _resolution
|
||||
) do
|
||||
with {:member, true} <- {:member, Actors.is_member?(actor_id, group_id)},
|
||||
with {:member, true} <- {:member, Actors.member?(actor_id, group_id)},
|
||||
%Page{} = page <- Resources.get_resources_for_folder(parent, page, limit) do
|
||||
{:ok, page}
|
||||
end
|
||||
|
@ -83,7 +83,7 @@ defmodule Mobilizon.GraphQL.Resolvers.Resource do
|
|||
Logger.debug("Getting resource for group with username #{username}")
|
||||
|
||||
with {:group, %Actor{id: group_id}} <- {:group, Actors.get_actor_by_name(username, :Group)},
|
||||
{:member, true} <- {:member, Actors.is_member?(actor_id, group_id)},
|
||||
{:member, true} <- {:member, Actors.member?(actor_id, group_id)},
|
||||
{:resource, %Resource{} = resource} <-
|
||||
{:resource, Resources.get_resource_by_group_and_path_with_preloads(group_id, path)} do
|
||||
{:ok, resource}
|
||||
|
@ -109,7 +109,7 @@ defmodule Mobilizon.GraphQL.Resolvers.Resource do
|
|||
}
|
||||
} = _resolution
|
||||
) do
|
||||
if Actors.is_member?(actor_id, group_id) do
|
||||
if Actors.member?(actor_id, group_id) do
|
||||
parent = get_eventual_parent(args)
|
||||
|
||||
if check_resource_owned_by_group(parent, group_id) do
|
||||
|
@ -155,7 +155,7 @@ defmodule Mobilizon.GraphQL.Resolvers.Resource do
|
|||
) do
|
||||
case Resources.get_resource_with_preloads(resource_id) do
|
||||
%Resource{actor_id: group_id} = resource ->
|
||||
if Actors.is_member?(actor_id, group_id) do
|
||||
if Actors.member?(actor_id, group_id) do
|
||||
case Actions.Update.update(resource, args, true, %{"actor" => actor_url}) do
|
||||
{:ok, _, %Resource{} = resource} ->
|
||||
{:ok, resource}
|
||||
|
@ -192,7 +192,7 @@ defmodule Mobilizon.GraphQL.Resolvers.Resource do
|
|||
) do
|
||||
with {:resource, %Resource{parent_id: _parent_id, actor_id: group_id} = resource} <-
|
||||
{:resource, Resources.get_resource_with_preloads(resource_id)},
|
||||
{:member, true} <- {:member, Actors.is_member?(actor_id, group_id)},
|
||||
{:member, true} <- {:member, Actors.member?(actor_id, group_id)},
|
||||
{:ok, _, %Resource{} = resource} <-
|
||||
Actions.Delete.delete(resource, actor) do
|
||||
{:ok, resource}
|
||||
|
|
|
@ -26,7 +26,7 @@ defmodule Mobilizon.GraphQL.Resolvers.Todos do
|
|||
context: %{current_actor: %Actor{id: actor_id}}
|
||||
} = _resolution
|
||||
) do
|
||||
with {:member, true} <- {:member, Actors.is_member?(actor_id, group_id)},
|
||||
with {:member, true} <- {:member, Actors.member?(actor_id, group_id)},
|
||||
%Page{} = page <- Todos.get_todo_lists_for_group(group, page, limit) do
|
||||
{:ok, page}
|
||||
else
|
||||
|
@ -50,7 +50,7 @@ defmodule Mobilizon.GraphQL.Resolvers.Todos do
|
|||
context: %{current_actor: %Actor{id: actor_id}}
|
||||
} = _resolution
|
||||
) do
|
||||
with {:member, true} <- {:member, Actors.is_member?(actor_id, group_id)},
|
||||
with {:member, true} <- {:member, Actors.member?(actor_id, group_id)},
|
||||
%Page{} = page <- Todos.get_todos_for_todo_list(todo_list, page, limit) do
|
||||
{:ok, page}
|
||||
else
|
||||
|
@ -70,7 +70,7 @@ defmodule Mobilizon.GraphQL.Resolvers.Todos do
|
|||
) do
|
||||
with {:todo, %TodoList{actor_id: group_id} = todo} <-
|
||||
{:todo, Todos.get_todo_list(todo_list_id)},
|
||||
{:member, true} <- {:member, Actors.is_member?(actor_id, group_id)} do
|
||||
{:member, true} <- {:member, Actors.member?(actor_id, group_id)} do
|
||||
{:ok, todo}
|
||||
else
|
||||
{:todo, nil} ->
|
||||
|
@ -93,7 +93,7 @@ defmodule Mobilizon.GraphQL.Resolvers.Todos do
|
|||
context: %{current_actor: %Actor{id: actor_id}}
|
||||
} = _resolution
|
||||
) do
|
||||
with {:member, true} <- {:member, Actors.is_member?(actor_id, group_id)},
|
||||
with {:member, true} <- {:member, Actors.member?(actor_id, group_id)},
|
||||
{:ok, _, %TodoList{} = todo_list} <-
|
||||
Actions.Create.create(
|
||||
:todo_list,
|
||||
|
@ -121,7 +121,7 @@ defmodule Mobilizon.GraphQL.Resolvers.Todos do
|
|||
# with {:is_owned, %Actor{} = actor} <- User.owns_actor(user, actor_id),
|
||||
# {:todo_list, %TodoList{actor_id: group_id} = todo_list} <-
|
||||
# {:todo_list, Todos.get_todo_list(todo_list_id)},
|
||||
# {:member, true} <- {:member, Actors.is_member?(actor_id, group_id)},
|
||||
# {:member, true} <- {:member, Actors.member?(actor_id, group_id)},
|
||||
# {:ok, _, %TodoList{} = todo} <-
|
||||
# Actions.Update.update_todo_list(todo_list, actor, true, %{}) do
|
||||
# {:ok, todo}
|
||||
|
@ -144,7 +144,7 @@ defmodule Mobilizon.GraphQL.Resolvers.Todos do
|
|||
# with {:is_owned, %Actor{} = actor} <- User.owns_actor(user, actor_id),
|
||||
# {:todo_list, %TodoList{actor_id: group_id} = todo_list} <-
|
||||
# {:todo_list, Todos.get_todo_list(todo_list_id)},
|
||||
# {:member, true} <- {:member, Actors.is_member?(actor_id, group_id)},
|
||||
# {:member, true} <- {:member, Actors.member?(actor_id, group_id)},
|
||||
# {:ok, _, %TodoList{} = todo} <-
|
||||
# Actions.Delete.delete_todo_list(todo_list, actor, true, %{}) do
|
||||
# {:ok, todo}
|
||||
|
@ -169,7 +169,7 @@ defmodule Mobilizon.GraphQL.Resolvers.Todos do
|
|||
{:todo, Todos.get_todo(todo_id)},
|
||||
{:todo_list, %TodoList{actor_id: group_id}} <-
|
||||
{:todo_list, Todos.get_todo_list(todo_list_id)},
|
||||
{:member, true} <- {:member, Actors.is_member?(actor_id, group_id)} do
|
||||
{:member, true} <- {:member, Actors.member?(actor_id, group_id)} do
|
||||
{:ok, todo}
|
||||
else
|
||||
{:todo, nil} ->
|
||||
|
@ -194,7 +194,7 @@ defmodule Mobilizon.GraphQL.Resolvers.Todos do
|
|||
) do
|
||||
with {:todo_list, %TodoList{actor_id: group_id} = _todo_list} <-
|
||||
{:todo_list, Todos.get_todo_list(todo_list_id)},
|
||||
{:member, true} <- {:member, Actors.is_member?(actor_id, group_id)},
|
||||
{:member, true} <- {:member, Actors.member?(actor_id, group_id)},
|
||||
{:ok, _, %Todo{} = todo} <-
|
||||
Actions.Create.create(
|
||||
:todo,
|
||||
|
@ -228,7 +228,7 @@ defmodule Mobilizon.GraphQL.Resolvers.Todos do
|
|||
{:todo, Todos.get_todo(todo_id)},
|
||||
{:todo_list, %TodoList{actor_id: group_id}} <-
|
||||
{:todo_list, Todos.get_todo_list(todo_list_id)},
|
||||
{:member, true} <- {:member, Actors.is_member?(actor_id, group_id)},
|
||||
{:member, true} <- {:member, Actors.member?(actor_id, group_id)},
|
||||
{:ok, _, %Todo{} = todo} <-
|
||||
Actions.Update.update(todo, args, true, %{}) do
|
||||
{:ok, todo}
|
||||
|
@ -259,7 +259,7 @@ defmodule Mobilizon.GraphQL.Resolvers.Todos do
|
|||
# {:todo, Todos.get_todo(todo_id)},
|
||||
# {:todo_list, %TodoList{actor_id: group_id}} <-
|
||||
# {:todo_list, Todos.get_todo_list(todo_list_id)},
|
||||
# {:member, true} <- {:member, Actors.is_member?(actor_id, group_id)},
|
||||
# {:member, true} <- {:member, Actors.member?(actor_id, group_id)},
|
||||
# {:ok, _, %Todo{} = todo} <-
|
||||
# Actions.Delete.delete_todo(todo, actor, true, %{}) do
|
||||
# {:ok, todo}
|
||||
|
|
|
@ -209,8 +209,8 @@ defmodule Mobilizon.Actors.Actor do
|
|||
@doc """
|
||||
Checks whether actor visibility is public.
|
||||
"""
|
||||
@spec is_public_visibility?(t) :: boolean
|
||||
def is_public_visibility?(%__MODULE__{visibility: visibility}) do
|
||||
@spec public_visibility?(t) :: boolean
|
||||
def public_visibility?(%__MODULE__{visibility: visibility}) do
|
||||
visibility in [:public, :unlisted]
|
||||
end
|
||||
|
||||
|
|
|
@ -710,8 +710,8 @@ defmodule Mobilizon.Actors do
|
|||
@doc """
|
||||
Returns whether the `actor_id` is a confirmed member for the group `parent_id`
|
||||
"""
|
||||
@spec is_member?(integer | String.t(), integer | String.t()) :: boolean()
|
||||
def is_member?(actor_id, parent_id) do
|
||||
@spec member?(integer | String.t(), integer | String.t()) :: boolean()
|
||||
def member?(actor_id, parent_id) do
|
||||
match?(
|
||||
{:ok, %Member{}},
|
||||
get_member(actor_id, parent_id, @member_roles)
|
||||
|
@ -721,8 +721,8 @@ defmodule Mobilizon.Actors do
|
|||
@doc """
|
||||
Returns whether the `actor_id` is a moderator for the group `parent_id`
|
||||
"""
|
||||
@spec is_moderator?(integer | String.t(), integer | String.t()) :: boolean()
|
||||
def is_moderator?(actor_id, parent_id) do
|
||||
@spec moderator?(integer | String.t(), integer | String.t()) :: boolean()
|
||||
def moderator?(actor_id, parent_id) do
|
||||
match?(
|
||||
{:ok, %Member{}},
|
||||
get_member(actor_id, parent_id, @moderator_roles)
|
||||
|
@ -732,8 +732,8 @@ defmodule Mobilizon.Actors do
|
|||
@doc """
|
||||
Returns whether the `actor_id` is an administrator for the group `parent_id`
|
||||
"""
|
||||
@spec is_administrator?(integer | String.t(), integer | String.t()) :: boolean()
|
||||
def is_administrator?(actor_id, parent_id) do
|
||||
@spec administrator?(integer | String.t(), integer | String.t()) :: boolean()
|
||||
def administrator?(actor_id, parent_id) do
|
||||
match?(
|
||||
{:ok, %Member{}},
|
||||
get_member(actor_id, parent_id, @administrator_roles)
|
||||
|
@ -922,8 +922,8 @@ defmodule Mobilizon.Actors do
|
|||
@doc """
|
||||
Returns whether the member is the last administrator for a group
|
||||
"""
|
||||
@spec is_only_administrator?(integer | String.t(), integer | String.t()) :: boolean()
|
||||
def is_only_administrator?(member_id, group_id) do
|
||||
@spec only_administrator?(integer | String.t(), integer | String.t()) :: boolean()
|
||||
def only_administrator?(member_id, group_id) do
|
||||
Member
|
||||
|> where(
|
||||
[m],
|
||||
|
|
|
@ -55,9 +55,10 @@ defmodule Mobilizon.Actors.Member do
|
|||
@doc """
|
||||
Checks whether the member is an administrator (admin or creator) of the group.
|
||||
"""
|
||||
def is_administrator(%__MODULE__{role: :administrator}), do: true
|
||||
def is_administrator(%__MODULE__{role: :creator}), do: true
|
||||
def is_administrator(%__MODULE__{}), do: false
|
||||
@spec administrator?(t()) :: boolean()
|
||||
def administrator?(%__MODULE__{role: :administrator}), do: true
|
||||
def administrator?(%__MODULE__{role: :creator}), do: true
|
||||
def administrator?(%__MODULE__{}), do: false
|
||||
|
||||
@doc false
|
||||
@spec changeset(t | Ecto.Schema.t(), map) :: Ecto.Changeset.t()
|
||||
|
|
|
@ -77,7 +77,7 @@ defmodule Mobilizon.Discussions do
|
|||
|> join(:left, [c], r in Comment, on: r.origin_comment_id == c.id)
|
||||
|> where([c, _], is_nil(c.in_reply_to_comment_id))
|
||||
|> where([c], c.visibility in ^@public_visibility)
|
||||
# TODO: This was added because we don't want to count deleted comments in total_replies.
|
||||
# This was added because we don't want to count deleted comments in total_replies.
|
||||
# However, it also excludes all top-level comments with deleted replies from being selected
|
||||
# |> where([_, r], is_nil(r.deleted_at))
|
||||
|> group_by([c], c.id)
|
||||
|
|
|
@ -515,8 +515,8 @@ defmodule Mobilizon.Events do
|
|||
|> Page.build_page(page, limit)
|
||||
end
|
||||
|
||||
@spec is_user_moderator_for_event?(integer | String.t(), integer | String.t()) :: boolean
|
||||
def is_user_moderator_for_event?(user_id, event_id) do
|
||||
@spec user_moderator_for_event?(integer | String.t(), integer | String.t()) :: boolean
|
||||
def user_moderator_for_event?(user_id, event_id) do
|
||||
Participant
|
||||
|> join(:inner, [p], a in Actor, on: p.actor_id == a.id)
|
||||
|> where([p, _a], p.event_id == ^event_id)
|
||||
|
@ -1492,14 +1492,14 @@ defmodule Mobilizon.Events do
|
|||
end
|
||||
|
||||
@spec filter_online(Ecto.Query.t(), map()) :: Ecto.Query.t()
|
||||
defp filter_online(query, %{type: :online}), do: is_online_fragment(query, true)
|
||||
defp filter_online(query, %{type: :online}), do: online_fragment_check(query, true)
|
||||
|
||||
defp filter_online(query, %{type: :in_person}), do: is_online_fragment(query, false)
|
||||
defp filter_online(query, %{type: :in_person}), do: online_fragment_check(query, false)
|
||||
|
||||
defp filter_online(query, _), do: query
|
||||
|
||||
@spec is_online_fragment(Ecto.Query.t(), boolean()) :: Ecto.Query.t()
|
||||
defp is_online_fragment(query, value) do
|
||||
@spec online_fragment_check(Ecto.Query.t(), boolean()) :: Ecto.Query.t()
|
||||
defp online_fragment_check(query, value) do
|
||||
where(query, [q], fragment("(?->>'is_online')::bool = ?", q.options, ^value))
|
||||
end
|
||||
|
||||
|
|
|
@ -49,8 +49,8 @@ defmodule Mobilizon.Events.Participant do
|
|||
We start by fetching the list of organizers and if there's only one of them
|
||||
and that it's the actor requesting leaving the event we return true.
|
||||
"""
|
||||
@spec is_not_only_organizer(integer | String.t(), integer | String.t()) :: boolean
|
||||
def is_not_only_organizer(event_id, actor_id) do
|
||||
@spec not_only_organizer?(integer | String.t(), integer | String.t()) :: boolean
|
||||
def not_only_organizer?(event_id, actor_id) do
|
||||
case Events.list_organizers_participants_for_event(event_id) do
|
||||
[%__MODULE__{actor: %Actor{id: participant_actor_id}}] ->
|
||||
participant_actor_id == actor_id
|
||||
|
|
|
@ -34,6 +34,10 @@ defmodule Mobilizon.Instances.InstanceActor do
|
|||
instance_actor
|
||||
|> cast(attrs, @attrs)
|
||||
|> validate_required(@required_attrs)
|
||||
|> validate_length(:domain, max: 254)
|
||||
|> validate_length(:instance_name, max: 254)
|
||||
|> validate_length(:software, max: 254)
|
||||
|> validate_length(:software_version, max: 254)
|
||||
|> unique_constraint(:domain)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -4,6 +4,7 @@ defmodule Mobilizon.Instances do
|
|||
"""
|
||||
alias Ecto.Adapters.SQL
|
||||
alias Mobilizon.Actors.{Actor, Follower}
|
||||
alias Mobilizon.Federation.ActivityPub.Relay
|
||||
alias Mobilizon.Instances.{Instance, InstanceActor}
|
||||
alias Mobilizon.Storage.{Page, Repo}
|
||||
import Ecto.Query
|
||||
|
@ -22,11 +23,15 @@ defmodule Mobilizon.Instances do
|
|||
|
||||
order_by_options = Keyword.new([{direction, order_by}])
|
||||
|
||||
%Actor{id: relay_id} = Relay.get_actor()
|
||||
|
||||
query =
|
||||
Instance
|
||||
|> join(:left, [i], ia in InstanceActor, on: i.domain == ia.domain)
|
||||
|> join(:left, [_i, ia], a in Actor, on: ia.actor_id == a.id)
|
||||
# following
|
||||
|> join(:left, [_i, _ia, a], f1 in Follower, on: f1.target_actor_id == a.id)
|
||||
# followed
|
||||
|> join(:left, [_i, _ia, a], f2 in Follower, on: f2.actor_id == a.id)
|
||||
|> select([i, ia, a, f1, f2], %{
|
||||
instance: i,
|
||||
|
@ -45,14 +50,27 @@ defmodule Mobilizon.Instances do
|
|||
if is_nil(filter_domain) or filter_domain == "" do
|
||||
query
|
||||
else
|
||||
where(query, [i], like(i.domain, ^"%#{filter_domain}%"))
|
||||
where(
|
||||
query,
|
||||
[i, ia],
|
||||
like(i.domain, ^"%#{filter_domain}%") or like(ia.instance_name, ^"%#{filter_domain}%")
|
||||
)
|
||||
end
|
||||
|
||||
query =
|
||||
case follow_status do
|
||||
:following -> where(query, [i, s], s.following == true)
|
||||
:followed -> where(query, [i, s], s.follower == true)
|
||||
:all -> query
|
||||
:following ->
|
||||
where(query, [_i, _ia, _a, f1], f1.actor_id == ^relay_id and f1.approved == true)
|
||||
|
||||
:followed ->
|
||||
where(
|
||||
query,
|
||||
[_i, _ia, _a, _f1, f2],
|
||||
f2.target_actor_id == ^relay_id and f2.approved == true
|
||||
)
|
||||
|
||||
:all ->
|
||||
query
|
||||
end
|
||||
|
||||
%Page{elements: elements} = paged_instances = Page.build_page(query, page, limit, :domain)
|
||||
|
|
|
@ -214,7 +214,7 @@ defmodule Mobilizon.Medias do
|
|||
query
|
||||
|> Repo.all(timeout: :infinity)
|
||||
|> Enum.filter(fn %Media{file: %File{url: url}} ->
|
||||
!url_is_also_a_profile_file?(url) && is_all_media_orphan?(url, expiration_date)
|
||||
!url_is_also_a_profile_file?(url) && all_media_orphan?(url, expiration_date)
|
||||
end)
|
||||
|> Enum.chunk_by(fn %Media{file: %File{url: url}} ->
|
||||
url
|
||||
|
@ -223,14 +223,14 @@ defmodule Mobilizon.Medias do
|
|||
end)
|
||||
end
|
||||
|
||||
defp is_all_media_orphan?(url, expiration_date) do
|
||||
defp all_media_orphan?(url, expiration_date) do
|
||||
url
|
||||
|> get_all_media_by_url()
|
||||
|> Enum.all?(&is_media_orphan?(&1, expiration_date))
|
||||
|> Enum.all?(&media_orphan?(&1, expiration_date))
|
||||
end
|
||||
|
||||
@spec is_media_orphan?(Media.t(), DateTime.t()) :: boolean()
|
||||
defp is_media_orphan?(%Media{id: media_id}, expiration_date) do
|
||||
@spec media_orphan?(Media.t(), DateTime.t()) :: boolean()
|
||||
defp media_orphan?(%Media{id: media_id}, expiration_date) do
|
||||
media_query =
|
||||
from(m in Media,
|
||||
as: :media,
|
||||
|
|
|
@ -7,6 +7,7 @@ defmodule Mobilizon.Storage.Ecto do
|
|||
import Ecto.Changeset, only: [fetch_change: 2, put_change: 3, get_field: 2]
|
||||
alias Ecto.{Changeset, Query}
|
||||
alias Mobilizon.Web.Endpoint
|
||||
alias Mobilizon.Web.Gettext, as: GettextBackend
|
||||
alias Mobilizon.Web.Router.Helpers, as: Routes
|
||||
|
||||
@doc """
|
||||
|
@ -56,4 +57,30 @@ defmodule Mobilizon.Storage.Ecto do
|
|||
changeset
|
||||
end
|
||||
end
|
||||
|
||||
def convert_ecto_errors(%Ecto.Changeset{} = changeset),
|
||||
do: Ecto.Changeset.traverse_errors(changeset, &translate_error/1)
|
||||
|
||||
# Translates an error message using gettext.
|
||||
defp translate_error({msg, opts}) do
|
||||
# Because error messages were defined within Ecto, we must
|
||||
# call the Gettext module passing our Gettext backend. We
|
||||
# also use the "errors" domain as translations are placed
|
||||
# in the errors.po file.
|
||||
# Ecto will pass the :count keyword if the error message is
|
||||
# meant to be pluralized.
|
||||
# On your own code and templates, depending on whether you
|
||||
# need the message to be pluralized or not, this could be
|
||||
# written simply as:
|
||||
#
|
||||
# dngettext "errors", "1 file", "%{count} files", count
|
||||
# dgettext "errors", "is invalid"
|
||||
#
|
||||
|
||||
if count = opts[:count] do
|
||||
Gettext.dngettext(GettextBackend, "errors", msg, msg, count, opts)
|
||||
else
|
||||
Gettext.dgettext(GettextBackend, "errors", msg, opts)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -55,14 +55,14 @@ defmodule Mobilizon.Service.DateTime do
|
|||
)
|
||||
end
|
||||
|
||||
@spec is_first_day_of_week(Date.t(), String.t()) :: boolean()
|
||||
defp is_first_day_of_week(%Date{} = date, locale) do
|
||||
@spec first_day_of_week?(Date.t(), String.t()) :: boolean()
|
||||
defp first_day_of_week?(%Date{} = date, locale) do
|
||||
Date.day_of_week(date) == Cldr.Calendar.first_day_for_locale(locale)
|
||||
end
|
||||
|
||||
@spec calculate_first_day_of_week(Date.t(), String.t()) :: Date.t()
|
||||
def calculate_first_day_of_week(%Date{} = date, locale \\ "en") do
|
||||
if is_first_day_of_week(date, locale),
|
||||
if first_day_of_week?(date, locale),
|
||||
do: date,
|
||||
else: calculate_first_day_of_week(Date.add(date, -1), locale)
|
||||
end
|
||||
|
@ -204,11 +204,11 @@ defmodule Mobilizon.Service.DateTime do
|
|||
compare_to_day = Keyword.get(options, :compare_to_day, Date.utc_today())
|
||||
locale = Keyword.get(options, :locale, "en")
|
||||
|
||||
is_first_day_of_week(compare_to_day, locale) && is_between_hours?(options)
|
||||
first_day_of_week?(compare_to_day, locale) && is_between_hours?(options)
|
||||
end
|
||||
|
||||
@spec is_delay_ok_since_last_notification_sent?(DateTime.t(), pos_integer()) :: boolean()
|
||||
def is_delay_ok_since_last_notification_sent?(
|
||||
@spec delay_ok_since_last_notification_sent?(DateTime.t(), pos_integer()) :: boolean()
|
||||
def delay_ok_since_last_notification_sent?(
|
||||
%DateTime{} = last_notification_sent,
|
||||
delay \\ 3_600
|
||||
) do
|
||||
|
@ -216,8 +216,8 @@ defmodule Mobilizon.Service.DateTime do
|
|||
:lt
|
||||
end
|
||||
|
||||
@spec is_same_day?(DateTime.t(), DateTime.t()) :: boolean()
|
||||
def is_same_day?(%DateTime{} = one, %DateTime{} = two) do
|
||||
@spec same_day?(DateTime.t(), DateTime.t()) :: boolean()
|
||||
def same_day?(%DateTime{} = one, %DateTime{} = two) do
|
||||
DateTime.to_date(one) == DateTime.to_date(two)
|
||||
end
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ defmodule Mobilizon.Service.Export.Common do
|
|||
def fetch_actor_event_feed(name, limit) do
|
||||
case Actors.get_actor_by_name(name) do
|
||||
%Actor{} = actor ->
|
||||
if Actor.is_public_visibility?(actor) do
|
||||
if Actor.public_visibility?(actor) do
|
||||
%Page{elements: events} = Events.list_public_upcoming_events_for_actor(actor, 1, limit)
|
||||
%Page{elements: posts} = Posts.get_public_posts_for_group(actor, 1, limit)
|
||||
{:ok, actor, events, posts}
|
||||
|
|
|
@ -265,7 +265,7 @@ defmodule Mobilizon.Service.Export.Feed do
|
|||
end
|
||||
|
||||
defp clear_actor_feed(%Actor{preferred_username: preferred_username} = actor) do
|
||||
if Actor.is_public_visibility?(actor) do
|
||||
if Actor.public_visibility?(actor) do
|
||||
Cachex.del(:feed, "actor_#{preferred_username}")
|
||||
end
|
||||
end
|
||||
|
|
|
@ -216,7 +216,7 @@ defmodule Mobilizon.Service.Export.ICalendar do
|
|||
end
|
||||
|
||||
defp clear_actor_feed(%Actor{preferred_username: preferred_username} = actor) do
|
||||
if Actor.is_public_visibility?(actor) do
|
||||
if Actor.public_visibility?(actor) do
|
||||
Cachex.del(:ics, "actor_#{preferred_username}")
|
||||
end
|
||||
end
|
||||
|
|
|
@ -13,8 +13,8 @@ defmodule Mobilizon.Service.HTTP.Utils do
|
|||
end
|
||||
end
|
||||
|
||||
@spec is_content_type?(Enum.t(), String.t() | list(String.t())) :: boolean
|
||||
def is_content_type?(headers, content_type) do
|
||||
@spec content_type_matches?(Enum.t(), String.t() | list(String.t())) :: boolean
|
||||
def content_type_matches?(headers, content_type) do
|
||||
headers
|
||||
|> get_header("Content-Type")
|
||||
|> content_type_header_matches(content_type)
|
||||
|
|
|
@ -12,8 +12,8 @@ defmodule Mobilizon.Service.Notifier.Email do
|
|||
|
||||
import Mobilizon.Service.DateTime,
|
||||
only: [
|
||||
is_delay_ok_since_last_notification_sent?: 1,
|
||||
is_delay_ok_since_last_notification_sent?: 2
|
||||
delay_ok_since_last_notification_sent?: 1,
|
||||
delay_ok_since_last_notification_sent?: 2
|
||||
]
|
||||
|
||||
require Logger
|
||||
|
@ -129,7 +129,7 @@ defmodule Mobilizon.Service.Notifier.Email do
|
|||
|
||||
# Delay ok since last notification
|
||||
defp match_group_notifications_setting(:one_hour, _, %DateTime{} = last_notification_sent, _) do
|
||||
is_delay_ok_since_last_notification_sent?(last_notification_sent)
|
||||
delay_ok_since_last_notification_sent?(last_notification_sent)
|
||||
end
|
||||
|
||||
# Delay ok since last notification
|
||||
|
@ -139,7 +139,7 @@ defmodule Mobilizon.Service.Notifier.Email do
|
|||
%DateTime{} = last_notification_sent,
|
||||
options
|
||||
) do
|
||||
is_delay_ok_since_last_notification_sent?(last_notification_sent, 3_600 * 23) and
|
||||
delay_ok_since_last_notification_sent?(last_notification_sent, 3_600 * 23) and
|
||||
Keyword.get(options, :recap, false) != false
|
||||
end
|
||||
|
||||
|
@ -149,7 +149,7 @@ defmodule Mobilizon.Service.Notifier.Email do
|
|||
%DateTime{} = last_notification_sent,
|
||||
options
|
||||
) do
|
||||
is_delay_ok_since_last_notification_sent?(last_notification_sent, 3_600 * 24 * 6) and
|
||||
delay_ok_since_last_notification_sent?(last_notification_sent, 3_600 * 24 * 6) and
|
||||
Keyword.get(options, :recap, false) != false
|
||||
end
|
||||
|
||||
|
|
|
@ -11,9 +11,7 @@ defmodule Mobilizon.Service.RichMedia.Parser do
|
|||
max_body: 2_000_000,
|
||||
timeout: 10_000,
|
||||
recv_timeout: 20_000,
|
||||
follow_redirect: true,
|
||||
# TODO: Remove me once Hackney/HTTPoison fixes their issue with TLS1.3 and OTP 23
|
||||
ssl: [{:versions, [:"tlsv1.2"]}]
|
||||
follow_redirect: true
|
||||
]
|
||||
|
||||
alias Mobilizon.Config
|
||||
|
@ -75,7 +73,7 @@ defmodule Mobilizon.Service.RichMedia.Parser do
|
|||
opts: @options
|
||||
)},
|
||||
{:is_html, _response_headers, true} <-
|
||||
{:is_html, response_headers, is_html?(response_headers)} do
|
||||
{:is_html, response_headers, html?(response_headers)} do
|
||||
body
|
||||
|> convert_utf8(response_headers)
|
||||
|> maybe_parse()
|
||||
|
@ -108,21 +106,21 @@ defmodule Mobilizon.Service.RichMedia.Parser do
|
|||
defp get_data_for_media(response_headers, url) do
|
||||
data = %{title: get_filename_from_headers(response_headers) || get_filename_from_url(url)}
|
||||
|
||||
if is_image?(response_headers) do
|
||||
if image?(response_headers) do
|
||||
Map.put(data, :image_remote_url, url)
|
||||
else
|
||||
data
|
||||
end
|
||||
end
|
||||
|
||||
@spec is_html?(Enum.t()) :: boolean
|
||||
defp is_html?(headers) do
|
||||
is_content_type?(headers, ["text/html", "application/xhtml"])
|
||||
@spec html?(Enum.t()) :: boolean
|
||||
defp html?(headers) do
|
||||
content_type_matches?(headers, ["text/html", "application/xhtml"])
|
||||
end
|
||||
|
||||
@spec is_image?(Enum.t()) :: boolean
|
||||
defp is_image?(headers) do
|
||||
is_content_type?(headers, ["image/"])
|
||||
@spec image?(Enum.t()) :: boolean
|
||||
defp image?(headers) do
|
||||
content_type_matches?(headers, ["image/"])
|
||||
end
|
||||
|
||||
@spec get_filename_from_headers(Enum.t()) :: String.t() | nil
|
||||
|
|
|
@ -81,7 +81,7 @@ defmodule Mobilizon.Service.Workers.LegacyNotifierBuilder do
|
|||
options
|
||||
) do
|
||||
mentionned_actor_ids
|
||||
|> Enum.filter(&Actors.is_member?(&1, Keyword.fetch!(options, :group_id)))
|
||||
|> Enum.filter(&Actors.member?(&1, Keyword.fetch!(options, :group_id)))
|
||||
|> users_from_actor_ids(Keyword.fetch!(options, :author_id))
|
||||
end
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ defmodule Mobilizon.Service.Workers.RefreshInstances do
|
|||
alias Mobilizon.Instances.{Instance, InstanceActor}
|
||||
alias Oban.Job
|
||||
require Logger
|
||||
import Mobilizon.Storage.Ecto, only: [convert_ecto_errors: 1]
|
||||
|
||||
@impl Oban.Worker
|
||||
@spec perform(Oban.Job.t()) :: :ok
|
||||
|
@ -56,6 +57,10 @@ defmodule Mobilizon.Service.Workers.RefreshInstances do
|
|||
Instances.create_instance_actor(args) do
|
||||
Logger.info("Saved instance actor details for domain #{host}")
|
||||
else
|
||||
{:error, %Ecto.Changeset{} = changeset} ->
|
||||
Logger.error("Unable to save instance \"#{domain}\" metadata")
|
||||
Logger.debug(convert_ecto_errors(changeset))
|
||||
|
||||
err ->
|
||||
Logger.error(inspect(err))
|
||||
end
|
||||
|
|
|
@ -16,7 +16,7 @@ defmodule Mobilizon.Service.Workers.SendActivityRecapWorker do
|
|||
only: [
|
||||
is_between_hours?: 1,
|
||||
is_between_hours_on_first_day?: 1,
|
||||
is_delay_ok_since_last_notification_sent?: 1
|
||||
delay_ok_since_last_notification_sent?: 1
|
||||
]
|
||||
|
||||
@impl Oban.Worker
|
||||
|
@ -108,7 +108,7 @@ defmodule Mobilizon.Service.Workers.SendActivityRecapWorker do
|
|||
"Testing if it's less than an hour since the last time we sent an activity recap"
|
||||
)
|
||||
|
||||
is_delay_ok_since_last_notification_sent?(last_notification_sent)
|
||||
delay_ok_since_last_notification_sent?(last_notification_sent)
|
||||
end
|
||||
|
||||
# If we're between notification hours
|
||||
|
|
|
@ -173,26 +173,26 @@ defmodule Mobilizon.Web.PageController do
|
|||
end
|
||||
end
|
||||
|
||||
@spec is_visible?(map) :: boolean()
|
||||
defp is_visible?(%{visibility: v}), do: v in [:public, :unlisted]
|
||||
defp is_visible?(%Tombstone{}), do: true
|
||||
defp is_visible?(_), do: true
|
||||
@spec visible?(map) :: boolean()
|
||||
defp visible?(%{visibility: v}), do: v in [:public, :unlisted]
|
||||
defp visible?(%Tombstone{}), do: true
|
||||
defp visible?(_), do: true
|
||||
|
||||
@spec ok_status?(cache_status) :: boolean()
|
||||
defp ok_status?(status), do: status in [:ok, :commit]
|
||||
|
||||
@typep cache_status :: :ok | :commit | :ignore
|
||||
|
||||
@spec ok_status_and_is_visible?(Plug.Conn.t(), cache_status, map()) :: boolean()
|
||||
defp ok_status_and_is_visible?(_conn, status, o),
|
||||
do: ok_status?(status) and is_visible?(o)
|
||||
@spec ok_status_and_visible?(Plug.Conn.t(), cache_status, map()) :: boolean()
|
||||
defp ok_status_and_visible?(_conn, status, o),
|
||||
do: ok_status?(status) and visible?(o)
|
||||
|
||||
defp checks?(conn, status, o) do
|
||||
cond do
|
||||
ok_status_and_is_visible?(conn, status, o) ->
|
||||
if is_local?(o) == :remote && get_format(conn) == "activity-json", do: :remote, else: true
|
||||
ok_status_and_visible?(conn, status, o) ->
|
||||
if local?(o) == :remote && get_format(conn) == "activity-json", do: :remote, else: true
|
||||
|
||||
is_person?(o) && get_format(conn) == "activity-json" ->
|
||||
person?(o) && get_format(conn) == "activity-json" ->
|
||||
true
|
||||
|
||||
true ->
|
||||
|
@ -200,9 +200,9 @@ defmodule Mobilizon.Web.PageController do
|
|||
end
|
||||
end
|
||||
|
||||
@spec is_local?(map()) :: boolean | :remote
|
||||
defp is_local?(%{local: local}), do: if(local, do: true, else: :remote)
|
||||
defp is_local?(_), do: false
|
||||
@spec local?(map()) :: boolean | :remote
|
||||
defp local?(%{local: local}), do: if(local, do: true, else: :remote)
|
||||
defp local?(_), do: false
|
||||
|
||||
@spec maybe_add_noindex_header(Plug.Conn.t(), map()) :: Plug.Conn.t()
|
||||
defp maybe_add_noindex_header(conn, %{visibility: visibility})
|
||||
|
@ -212,9 +212,9 @@ defmodule Mobilizon.Web.PageController do
|
|||
|
||||
defp maybe_add_noindex_header(conn, _), do: conn
|
||||
|
||||
@spec is_person?(Actor.t()) :: boolean()
|
||||
defp is_person?(%Actor{type: :Person}), do: true
|
||||
defp is_person?(_), do: false
|
||||
@spec person?(Actor.t()) :: boolean()
|
||||
defp person?(%Actor{type: :Person}), do: true
|
||||
defp person?(_), do: false
|
||||
|
||||
defp maybe_add_content_type_header(conn) do
|
||||
case get_format(conn) do
|
||||
|
|
|
@ -87,8 +87,6 @@ defmodule Mobilizon.Web.Email.Group do
|
|||
end
|
||||
end
|
||||
|
||||
# TODO : def send_confirmation_to_inviter()
|
||||
|
||||
@member_roles [:administrator, :moderator, :member]
|
||||
@spec send_group_suspension_notification(Member.t()) :: :ok
|
||||
def send_group_suspension_notification(%Member{actor: %Actor{user_id: nil}}), do: :ok
|
||||
|
|
|
@ -124,6 +124,4 @@ defmodule Mobilizon.Web.Email.Member do
|
|||
:ok
|
||||
end
|
||||
end
|
||||
|
||||
# TODO : def send_confirmation_to_inviter()
|
||||
end
|
||||
|
|
|
@ -71,13 +71,7 @@ defmodule Mobilizon.Web.MediaProxy do
|
|||
@compile {:no_warn_undefined, {:crypto, :mac, 4}}
|
||||
@compile {:no_warn_undefined, {:crypto, :hmac, 3}}
|
||||
defp sha_hmac(key, url) do
|
||||
# :crypto.hmac was removed in OTP24, but :crypto.mac was added in OTP 22.1
|
||||
# TODO: Remove me when we don't support OTP 21/22 anymore
|
||||
if function_exported?(:crypto, :mac, 4) do
|
||||
:crypto.mac(:hmac, :sha, key, url)
|
||||
else
|
||||
:crypto.hmac(:sha, key, url)
|
||||
end
|
||||
:crypto.mac(:hmac, :sha, key, url)
|
||||
end
|
||||
|
||||
@spec filename(String.t()) :: String.t() | nil
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
timezone: @timezone,
|
||||
locale: @locale
|
||||
) %>
|
||||
<% is_same_day?(@start_date, @end_date) -> %>
|
||||
<% same_day?(@start_date, @end_date) -> %>
|
||||
<strong>
|
||||
<%= gettext("On %{date} from %{start_time} to %{end_time}",
|
||||
date: datetime_to_date_string(@start_date, @locale),
|
||||
|
|
|
@ -1 +1 @@
|
|||
<%= cond do %><% @end_date == nil -> %><%= render("date/event_tz_date.text", date: @start_date, event: @event, timezone: @timezone, locale: @locale) %><% is_same_day?(@start_date, @end_date) -> %><%= gettext "On %{date} from %{start_time} to %{end_time}", date: datetime_to_date_string(@start_date, @locale), start_time: datetime_to_time_string(@start_date, @locale), end_time: datetime_to_time_string(@end_date, @locale) %><%= if @event.options.timezone != @timezone do %> <%= gettext "🌐 %{timezone} %{offset}", timezone: @event.options.timezone, offset: Cldr.DateTime.Formatter.zone_gmt(@start_date) %><% end %><% true -> %><%= gettext "From the %{start} to the %{end}", start: datetime_to_string(@start_date, @locale, :short), end: datetime_to_string(@end_date, @locale, :short) %><%= if @event.options.timezone != @timezone do %> <%= gettext "🌐 %{timezone} %{offset}", timezone: @event.options.timezone, offset: Cldr.DateTime.Formatter.zone_gmt(@start_date) %><% end %><% end %>
|
||||
<%= cond do %><% @end_date == nil -> %><%= render("date/event_tz_date.text", date: @start_date, event: @event, timezone: @timezone, locale: @locale) %><% same_day?(@start_date, @end_date) -> %><%= gettext "On %{date} from %{start_time} to %{end_time}", date: datetime_to_date_string(@start_date, @locale), start_time: datetime_to_time_string(@start_date, @locale), end_time: datetime_to_time_string(@end_date, @locale) %><%= if @event.options.timezone != @timezone do %> <%= gettext "🌐 %{timezone} %{offset}", timezone: @event.options.timezone, offset: Cldr.DateTime.Formatter.zone_gmt(@start_date) %><% end %><% true -> %><%= gettext "From the %{start} to the %{end}", start: datetime_to_string(@start_date, @locale, :short), end: datetime_to_string(@end_date, @locale, :short) %><%= if @event.options.timezone != @timezone do %> <%= gettext "🌐 %{timezone} %{offset}", timezone: @event.options.timezone, offset: Cldr.DateTime.Formatter.zone_gmt(@start_date) %><% end %><% end %>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
document.documentElement.classList.remove('dark')
|
||||
}
|
||||
</script>
|
||||
<%= if is_root(assigns) do %>
|
||||
<%= if root?(assigns) do %>
|
||||
<link rel="preload" href="/img/shape-1.svg" as="image" />
|
||||
<link rel="preload" href="/img/shape-2.svg" as="image" />
|
||||
<link rel="preload" href="/img/shape-3.svg" as="image" />
|
||||
|
|
|
@ -25,7 +25,7 @@ defmodule Mobilizon.Web.EmailView do
|
|||
defdelegate datetime_tz_convert(datetime, timezone), to: DateTimeRenderer
|
||||
defdelegate datetime_relative(datetime, locale \\ "en"), to: DateTimeRenderer
|
||||
defdelegate render_address(address), to: Address
|
||||
defdelegate is_same_day?(one, two), to: DateTimeRenderer
|
||||
defdelegate same_day?(one, two), to: DateTimeRenderer
|
||||
defdelegate display_name(actor), to: Actor
|
||||
defdelegate preferred_username_and_domain(actor), to: Actor
|
||||
|
||||
|
|
|
@ -87,8 +87,8 @@ defmodule Mobilizon.Web.PageView do
|
|||
assigns |> Map.get(:locale, "en") |> get_language_direction()
|
||||
end
|
||||
|
||||
@spec is_root(map()) :: boolean()
|
||||
def is_root(assigns) do
|
||||
@spec root?(map()) :: boolean()
|
||||
def root?(assigns) do
|
||||
assigns |> Map.get(:conn, %{request_path: "/"}) |> Map.get(:request_path, "/") == "/"
|
||||
end
|
||||
end
|
||||
|
|
|
@ -21,6 +21,10 @@
|
|||
"**/*.{js,ts,vue}": [
|
||||
"eslint --fix",
|
||||
"prettier --write"
|
||||
],
|
||||
"**/*.{ex,exs,eex,heex}": [
|
||||
"mix format",
|
||||
"mix credo"
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
|
|
|
@ -8,15 +8,15 @@
|
|||
## to merge POT files into PO files.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"PO-Revision-Date: 2022-12-19 04:14+0000\n"
|
||||
"Last-Translator: Kristoffer Grundström <swedishsailfishosuser@tutanota.com>\n"
|
||||
"PO-Revision-Date: 2024-01-19 09:47+0000\n"
|
||||
"Last-Translator: drkfrd <drkfrd@users.noreply.weblate.framasoft.org>\n"
|
||||
"Language-Team: Swedish <https://weblate.framasoft.org/projects/mobilizon/"
|
||||
"activity/sv/>\n"
|
||||
"Language: sv\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||
"X-Generator: Weblate 4.14.1\n"
|
||||
"X-Generator: Weblate 5.3.1\n"
|
||||
|
||||
#: lib/web/templates/email/activity/_member_activity_item.html.heex:14
|
||||
#: lib/web/templates/email/activity/_member_activity_item.text.eex:12
|
||||
|
@ -478,12 +478,12 @@ msgstr "%{profile} lade till medlemmen %{member}."
|
|||
#: lib/web/templates/email/activity/_event_activity_item.text.eex:31
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "%{profile} joined your event %{event}."
|
||||
msgstr ""
|
||||
msgstr "%{profile} gick med i ditt evenemang %{event}."
|
||||
|
||||
#: lib/web/views/email_view.ex:61
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "An anonymous profile"
|
||||
msgstr ""
|
||||
msgstr "En anonym profil"
|
||||
|
||||
#: lib/web/templates/email/email_anonymous_activity.html.heex:107
|
||||
#: lib/web/templates/email/email_anonymous_activity.text.eex:14
|
||||
|
@ -510,7 +510,7 @@ msgstr "%{profile} nämnde dig i en kommentar under händelsen %{event}."
|
|||
#: lib/service/activity/renderer/conversation.ex:36
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "%{profile} replied to your message"
|
||||
msgstr ""
|
||||
msgstr "%{profil} svarade på ditt meddelande"
|
||||
|
||||
#: lib/web/templates/email/activity/_conversation_activity_item.html.heex:10
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
|
@ -520,31 +520,35 @@ msgstr "%{profile} svarade på diskussionen %{discussion}."
|
|||
#: lib/web/templates/email/activity/_conversation_activity_item.text.eex:6
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "%{profile} replied you in a conversation."
|
||||
msgstr ""
|
||||
msgstr "%{profile} svarade dig i en konversation."
|
||||
|
||||
#: lib/service/activity/renderer/conversation.ex:49
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "%{profile} sent a private message about event %{event}"
|
||||
msgstr ""
|
||||
msgstr "%{profile} skickade ett privat meddelande om händelsen %{event}"
|
||||
|
||||
#: lib/service/activity/renderer/conversation.ex:23
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "%{profile} sent you a message"
|
||||
msgstr ""
|
||||
msgstr "%{profil} skickade ett meddelande till dig"
|
||||
|
||||
#: lib/web/email/activity.ex:52
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Informations about your event %{event}"
|
||||
msgstr ""
|
||||
msgstr "Information om ditt evenemang %{event}"
|
||||
|
||||
#: lib/web/templates/email/email_anonymous_activity.html.heex:118
|
||||
#: lib/web/templates/email/email_anonymous_activity.text.eex:20
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "It might give details on how to join the event, so make sure to read it appropriately."
|
||||
msgstr ""
|
||||
"Den kan innehålla information om hur du går med i evenemanget, så se till "
|
||||
"att läsa den ordentligt."
|
||||
|
||||
#: lib/web/templates/email/email_anonymous_activity.html.heex:156
|
||||
#: lib/web/templates/email/email_anonymous_activity.text.eex:28
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "This information is sent privately to you as a person who registered for this event. Share the informations above with other people with caution."
|
||||
msgstr ""
|
||||
"Denna information skickas privat till dig som registrerat dig för detta "
|
||||
"evenemang. Dela informationen ovan med andra personer med försiktighet."
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
defmodule Mobilizon.Storage.Repo.Migrations.ChangeActorInstanceDescriptionTypeToText do
|
||||
use Ecto.Migration
|
||||
|
||||
def up do
|
||||
alter table(:instance_actors) do
|
||||
modify(:instance_description, :text)
|
||||
end
|
||||
end
|
||||
|
||||
def down do
|
||||
alter table(:instance_actors) do
|
||||
modify(:instance_description, :string)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1641,5 +1641,6 @@
|
|||
"Announcements for {eventTitle}": "Announcements for {eventTitle}",
|
||||
"Visit {instance_domain}": "Visit {instance_domain}",
|
||||
"Software details: {software_details}": "Software details: {software_details}",
|
||||
"Only instances with an application actor can be followed": "Only instances with an application actor can be followed"
|
||||
"Only instances with an application actor can be followed": "Only instances with an application actor can be followed",
|
||||
"Domain or instance name": "Domain or instance name"
|
||||
}
|
|
@ -1635,5 +1635,6 @@
|
|||
"Announcements for {eventTitle}": "Annonces pour {eventTitle}",
|
||||
"Visit {instance_domain}": "Visiter {instance_domain}",
|
||||
"Software details: {software_details}": "Détails du logiciel : {software_details}",
|
||||
"Only instances with an application actor can be followed": "Seules les instances avec un acteur application peuvent être suivies"
|
||||
"Only instances with an application actor can be followed": "Seules les instances avec un acteur application peuvent être suivies",
|
||||
"Domain or instance name": "Domaine ou nom de l'instance"
|
||||
}
|
||||
|
|
|
@ -47,6 +47,17 @@
|
|||
"Accept": "Elfogadás",
|
||||
"Accept follow": "Követés elfogadása",
|
||||
"Accepted": "Elfogadva",
|
||||
"Access followed groups": "Követett csoportok elérése",
|
||||
"Access group activities": "Csoport tevékenységeinek elérése",
|
||||
"Access group discussions": "Csoport témáinak elérése",
|
||||
"Access group events": "Csoport eseményeinek elérése",
|
||||
"Access group followers": "Csoport követőinek elérése",
|
||||
"Access group members": "Csoport tagjainak elérése",
|
||||
"Access group memberships": "Csoporttagságok elérése",
|
||||
"Access group todo-lists": "Csoport teendőlistáinak elérése",
|
||||
"Access organized events": "Szervezett események elérése",
|
||||
"Access participations": "Résztvevők elérése",
|
||||
"Access your group's resources": "Csoport bejegyzéseinek elérése",
|
||||
"Accessibility": "Akadálymentesítés",
|
||||
"Accessible only by link": "Csak hivatkozáson keresztül érhető el",
|
||||
"Accessible only to members": "Csak tagoknak érhető el",
|
||||
|
@ -99,6 +110,7 @@
|
|||
"An event from one of my groups has been published": "Az egyik csoportomtól származó esemény közzé lett téve",
|
||||
"An event from one of my groups has been updated or deleted": "Az egyik csoportomtól származó esemény frissítve vagy törölve lett",
|
||||
"An instance is an installed version of the Mobilizon software running on a server. An instance can be run by anyone using the {mobilizon_software} or other federated apps, aka the “fediverse”. This instance's name is {instance_name}. Mobilizon is a federated network of multiple instances (just like email servers), users registered on different instances may communicate even though they didn't register on the same instance.": "A példány a kiszolgálón futó Mobilizon szoftvernek egy telepített verziója. Egy példányt bárki futtathat a {mobilizon_software} vagy egyéb föderált alkalmazások (vagy más néven „födiverzum”) használatával. Ennek a példánynak a neve {instance_name}. A Mobilizon több példány föderált hálózata (hasonlóan a levelezési kiszolgálókhoz). A különböző példányokon regisztrált felhasználók még akkor is kommunikálhatnak egymással, ha nem regisztráltak ugyanarra a példányra.",
|
||||
"An “application programming interface” or “API” is a communication protocol that allows software components to communicate with each other. The Mobilizon API, for example, can allow third-party software tools to communicate with Mobilizon instances to carry out certain actions, such as posting events, automatically and remotely.": "Egy „alkalmazásprogramozási interfész” vagy „API” egy kommunikációs protokoll, amellyel a szoftverösszetevők kommunikálhatnak egymással. A Mobilizon API-val, például, harmadik féltől származó szoftvereszközök is kommunikálhatnak a Mobilizon példányokkal, és így végrehajthatnak bizonyos műveleteket, mint az események automatikus létrehozása távolról.",
|
||||
"And {number} comments": "és {number} hozzászólást tettek közzé",
|
||||
"Announcements and mentions notifications are always sent straight away.": "A közlemények és az említések értesítései mindig azonnal elküldésre kerülnek.",
|
||||
"Anonymous participant": "Névtelen részvétel",
|
||||
|
@ -112,8 +124,11 @@
|
|||
"Anyone can request being a member, but an administrator needs to approve the membership.": "Bárki kérheti, hogy tag lehessen, de egy adminisztrátornak jóvá kell hagynia a tagságot.",
|
||||
"Anyone wanting to be a member from your group will be able to from your group page.": "Bárki, aki a csoportja tagja szeretne lenni, a csoportja oldaláról lesz képes csatlakozni.",
|
||||
"Application": "Alkalmazás",
|
||||
"Application not found": "Az alkalmazás nem található",
|
||||
"Application was revoked": "Az alkalmazás vissza lett vonva",
|
||||
"Apply filters": "Szűrők alkalmazása",
|
||||
"Approve member": "Tag jóváhagyása",
|
||||
"Apps": "Alkalmazások",
|
||||
"Are you really sure you want to delete your whole account? You'll lose everything. Identities, settings, events created, messages and participations will be gone forever.": "Egészen biztos abban, hogy a teljes fiókot törölni szeretné? Mindent el fog veszíteni! A személyazonosságok, a beállítások, a létrehozott események, az üzenetek és a részvételek örökre eltűnnek.",
|
||||
"Are you sure you want to <b>completely delete</b> this group? All members - including remote ones - will be notified and removed from the group, and <b>all of the group data (events, posts, discussions, todos…) will be irretrievably destroyed</b>.": "Biztosan <b>teljesen törölni</b> szeretné ezt a csoportot? Az összes tag – beleértve a távoliakat is – értesítve lesz, és eltávolításra kerül a csoportból, valamint <b>az összes csoportadat (események, bejegyzések, megbeszélések, tennivalók…) visszavonhatatlanul meg lesznek semmisítve</b>.",
|
||||
"Are you sure you want to <b>delete</b> this comment? This action cannot be undone.": "Biztosan <b>törölni</b> szeretné ezt a hozzászólást? Ezt a műveletet nem lehet visszavonni.",
|
||||
|
@ -131,7 +146,11 @@
|
|||
"Ask your instance admin to {enable_feature}.": "Kérje meg a példány adminisztrátorát, hogy {enable_feature}.",
|
||||
"Assigned to": "Hozzárendelve ehhez",
|
||||
"Atom feed for events and posts": "Atom hírforrás az eseményekhez és a bejegyzésekhez",
|
||||
"Attending": "Részvétel",
|
||||
"Attending": "Részt vesz",
|
||||
"Authorize": "Engedélyezés",
|
||||
"Authorize application": "Alkalmazás engedélyezése",
|
||||
"Authorized on {authorization_date}": "Engedélyezve: {authorization_date}",
|
||||
"Autorize this application to access your account?": "Engedélyezi, hogy ez az alkalmazás hozzáférjen a fiókjához?",
|
||||
"Avatar": "Profilkép",
|
||||
"Back to group list": "Vissza a csoportokhoz",
|
||||
"Back to homepage": "Vissza a kezdőlapra",
|
||||
|
@ -214,6 +233,7 @@
|
|||
"Confirmed: Will happen": "Megerősítve: meg fog történni",
|
||||
"Congratulations, your account is now created!": "Gratulálunk, a fiókja most létrejött!",
|
||||
"Contact": "Kapcsolat",
|
||||
"Continue": "Folytatás",
|
||||
"Continue editing": "Szerkesztés folytatása",
|
||||
"Cookies and Local storage": "Sütik és helyi tároló",
|
||||
"Copy URL to clipboard": "URL másolás a vágólapra",
|
||||
|
@ -227,6 +247,7 @@
|
|||
"Create a new group": "Új csoport létrehozása",
|
||||
"Create a new identity": "Új személyazonosság létrehozása",
|
||||
"Create a new list": "Új lista létrehozása",
|
||||
"Create a new metadata element": "Új metaadatelem létrehozása",
|
||||
"Create a new profile": "Új profil létrehozása",
|
||||
"Create a pad": "Dokumentum létrehozása",
|
||||
"Create a videoconference": "Videokonferencia létrehozása",
|
||||
|
@ -234,11 +255,14 @@
|
|||
"Create discussion": "Megbeszélés létrehozása",
|
||||
"Create event": "Esemény létrehozása",
|
||||
"Create group": "Csoport létrehozása",
|
||||
"Create group discussions": "Csoport témáinak létrehozása",
|
||||
"Create group resources": "Csoport bejegyzéseinek létrehozása",
|
||||
"Create identity": "Személyazonosság létrehozása",
|
||||
"Create my event": "Saját esemény létrehozása",
|
||||
"Create my group": "Saját csoport létrehozása",
|
||||
"Create my profile": "Saját profil létrehozása",
|
||||
"Create new links": "Új hivatkozások létrehozása",
|
||||
"Create new profiles": "Új profilok létrehozása",
|
||||
"Create resource": "Erőforrás létrehozása",
|
||||
"Create the discussion": "A megbeszélés létrehozása",
|
||||
"Create to-do lists for all the tasks you need to do, assign them and set due dates.": "Hozzon létre tennivalólistákat az összes elvégzendő feladathoz, rendelje hozzá őket, és állítson be a határidőket.",
|
||||
|
@ -265,13 +289,19 @@
|
|||
"Default Mobilizon terms": "Alapértelmezett Mobilizon használati feltételek",
|
||||
"Delete": "Törlés",
|
||||
"Delete account": "Fiók törlése",
|
||||
"Delete comments": "Hozzászólások törlése",
|
||||
"Delete conversation": "Beszélgetés törlése",
|
||||
"Delete discussion": "Megbeszélés törlése",
|
||||
"Delete event": "Esemény törlése",
|
||||
"Delete events": "Események törlése",
|
||||
"Delete everything": "Minden törlése",
|
||||
"Delete group": "Csoport törlése",
|
||||
"Delete group discussions": "Csoport témáinak törlése",
|
||||
"Delete group posts": "Csoport bejegyzéseinek törlése",
|
||||
"Delete group resources": "Csoport erőforrásainak törlése",
|
||||
"Delete my account": "Saját fiók törlése",
|
||||
"Delete post": "Bejegyzés törlése",
|
||||
"Delete profiles": "Profilok törlése",
|
||||
"Delete this discussion": "A megbeszélés törlése",
|
||||
"Delete this identity": "A személyazonosság törlése",
|
||||
"Delete your identity": "Az Ön személyazonosságának törlése",
|
||||
|
@ -285,6 +315,7 @@
|
|||
"Describe your event": "Írja le az eseményt",
|
||||
"Description": "Leírás",
|
||||
"Details": "Részletek",
|
||||
"Device activation": "Eszköz aktiválása",
|
||||
"Didn't receive the instructions?": "Nem kapta meg az utasításokat?",
|
||||
"Disabled": "Letiltva",
|
||||
"Discussions": "Megbeszélések",
|
||||
|
@ -323,6 +354,7 @@
|
|||
"Emails usually don't contain capitals, make sure you haven't made a typo.": "Az e-mail-címek általában nem tartalmaznak nagybetűt. Győződjön meg arról, hogy nem írta-e el.",
|
||||
"Enabled": "Engedélyezve",
|
||||
"Ends on…": "Befejeződik…",
|
||||
"Enter the code displayed on your device": "Adja meg az eszközén megjelenített kódot",
|
||||
"Enter the link URL": "Adja meg a hivatkozás URL-ét",
|
||||
"Enter your email address below, and we'll email you instructions on how to change your password.": "Adja meg lent az e-mail-címét, és elküldjük e-mailben az utasításokat, hogy hogyan változtathatja meg a jelszavát.",
|
||||
"Enter your own privacy policy. HTML tags allowed. The {mobilizon_privacy_policy} is provided as template.": "Adja meg a saját adatvédelmi irányelveit. A HTML címkék engedélyezettek. A {mobilizon_privacy_policy} meg van adva sablonként.",
|
||||
|
@ -537,6 +569,7 @@
|
|||
"Last published events": "Legutóbb közzétett események",
|
||||
"Last seen on": "Legutóbb látva:",
|
||||
"Last sign-in": "Utolsó bejelentkezés",
|
||||
"Last used on {last_used_date}": "Legutóbb használva: {last_used_date}",
|
||||
"Last week": "Múlt hét",
|
||||
"Latest posts": "Legutóbbi bejegyzések",
|
||||
"Learn more": "Tudjon meg többet",
|
||||
|
@ -572,7 +605,12 @@
|
|||
"Login status": "Bejelentkezési állapot",
|
||||
"Main languages you/your moderators speak": "Fő nyelvek, amelyeken Ön vagy a moderátorai beszélnek",
|
||||
"Make sure that all words are spelled correctly.": "Győződjön meg róla, hogy minden szót helyesen írt le.",
|
||||
"Manage activity settings": "Tevékenységbeállítások kezelése",
|
||||
"Manage event participations": "Eseményrészvételek kezelése",
|
||||
"Manage group members": "Csoport tagjainak kezelése",
|
||||
"Manage group memberships": "Csoporttagságok kezelése",
|
||||
"Manage participations": "Részvételek kezelése",
|
||||
"Manage push notification settings": "Leküldéses értesítések beállításainak kezelése",
|
||||
"Manually approve new followers": "Új követők kézi jóváhagyása",
|
||||
"Manually invite new members": "Új tagok meghívása kézzel",
|
||||
"Map": "Térkép",
|
||||
|
@ -603,6 +641,7 @@
|
|||
"Moderation log": "Moderálási napló",
|
||||
"Moderation logs": "Moderálási naplók",
|
||||
"Moderator": "Moderátor",
|
||||
"Modify all of your account's data": "Az összes fiókadatának módosítása",
|
||||
"More options": "További lehetőségek",
|
||||
"Most recently published": "Legújabban közzétéve",
|
||||
"Move": "Áthelyezés",
|
||||
|
@ -617,6 +656,7 @@
|
|||
"NOTE! The default terms have not been checked over by a lawyer and thus are unlikely to provide full legal protection for all situations for an instance admin using them. They are also not specific to all countries and jurisdictions. If you are unsure, please check with a lawyer.": "MEGJEGYZÉS! Az alapértelmezett használati feltételek nem lettek jogász által ellenőrizve, és ennélfogva nem valószínű, hogy minden helyzetben teljes jogi védelmet biztosít az azt használó példány adminisztrátorának. Továbbá nem tér ki az összes országra és igazságszolgáltatásra. Ha nem biztos a dolgában, akkor ellenőriztesse egy jogásszal.",
|
||||
"Name": "Név",
|
||||
"Navigated to {pageTitle}": "Navigálva ide: {pageTitle}",
|
||||
"Never used": "Sosem volt használva",
|
||||
"New discussion": "Új megbeszélés",
|
||||
"New email": "Új e-mail",
|
||||
"New folder": "Új mappa",
|
||||
|
@ -786,6 +826,7 @@
|
|||
"Post a comment": "Hozzászólás beküldése",
|
||||
"Post a reply": "Válasz beküldése",
|
||||
"Post body": "Bejegyzés törzse",
|
||||
"Post comments": "Hozzászólások közzététele",
|
||||
"Post {eventTitle} reported": "A(z) {eventTitle} bejegyzés jelentve",
|
||||
"Postal Code": "Irányítószám",
|
||||
"Posts": "Bejegyzések",
|
||||
|
@ -816,6 +857,8 @@
|
|||
"Public preview": "Nyilvános előnézet",
|
||||
"Publication date": "Közzététel dátuma",
|
||||
"Publish": "Közzététel",
|
||||
"Publish events": "Események közzététele",
|
||||
"Publish group posts": "Csoport bejegyzéseinek közzététele",
|
||||
"Published by {name}": "Közzétette: {name}",
|
||||
"Published events with <b>{comments}</b> comments and <b>{participations}</b> confirmed participations": "Közzétett események <b>{comments}</b> hozzászólással és <b>{participations}</b> megerősített részvétellel",
|
||||
"Published events with {comments} comments and {participations} confirmed participations": "Események közzétéve {comments} hozzászólással és {participations} megerősített résztvevővel",
|
||||
|
@ -823,6 +866,7 @@
|
|||
"Quote": "Idézet",
|
||||
"RSS/Atom Feed": "RSS/Atom hírforrás",
|
||||
"Radius": "Sugár",
|
||||
"Read all of your account's data": "Az összes fiókadatának olvasása",
|
||||
"Recap every week": "Rövid összegzés minden héten",
|
||||
"Receive one email for each activity": "Egy e-mail fogadása minden tevékenységnél",
|
||||
"Receive one email per request": "Egy levél fogadása kérésenként",
|
||||
|
@ -848,6 +892,7 @@
|
|||
"Remember my participation in this browser": "Emlékezzen a részvételemre ebben a böngészőben",
|
||||
"Remove": "Eltávolítás",
|
||||
"Remove link": "Hivatkozás eltávolítása",
|
||||
"Remove uploaded media": "Feltöltött média eltávolítása",
|
||||
"Rename": "Átnevezés",
|
||||
"Rename resource": "Erőforrás átnevezése",
|
||||
"Reopen": "Újranyitás",
|
||||
|
@ -855,6 +900,9 @@
|
|||
"Reply": "Válasz",
|
||||
"Report": "Jelentés",
|
||||
"Report #{reportNumber}": "#{reportNumber} jelentés",
|
||||
"Report as ham": "Jelentés nem kéretlenként",
|
||||
"Report as spam": "Jelentés kéretlenként",
|
||||
"Report as undetected spam": "Jelentés nem észlelt kéretlen tartalomként",
|
||||
"Report reason": "Jelentés oka",
|
||||
"Report status": "Állapotjelentés",
|
||||
"Report this comment": "Hozzászólás jelentése",
|
||||
|
@ -883,6 +931,7 @@
|
|||
"Resources": "Erőforrások",
|
||||
"Restricted": "Korlátozott",
|
||||
"Return to the group page": "Visszatérés a csoport oldalára",
|
||||
"Revoke": "Visszavonás",
|
||||
"Right now": "Épp most",
|
||||
"Role": "Szerep",
|
||||
"Rules": "Szabályok",
|
||||
|
@ -892,7 +941,7 @@
|
|||
"Save draft": "Piszkozat mentése",
|
||||
"Schedule": "Ütemterv",
|
||||
"Search": "Keresés",
|
||||
"Search events, groups, etc.": "Események, csoportok stb. keresése",
|
||||
"Search events, groups, etc.": "Események, csoportok és egyebek keresése",
|
||||
"Search target": "Cél keresése",
|
||||
"Searching…": "Keresés…",
|
||||
"Select a category": "Válasszon egy kategóriát",
|
||||
|
@ -943,6 +992,7 @@
|
|||
"Stop following instance": "Példány követésének leállítása",
|
||||
"Street": "Utca",
|
||||
"Submit": "Elküldés",
|
||||
"Submit to Akismet": "Beküldés az Akismetnek",
|
||||
"Subtitles": "Feliratok",
|
||||
"Suggestions:": "Javaslatok:",
|
||||
"Suspend": "Felfüggesztés",
|
||||
|
@ -973,6 +1023,7 @@
|
|||
"The actual number of participants may differ, as this event is hosted on another instance.": "A résztvevők tényleges száma eltérhet, mivel ez az esemény egy másik példányon van kiszolgálva.",
|
||||
"The calc will be created on {service}": "A táblázat itt lesz létrehozva: {service}",
|
||||
"The content came from another server. Transfer an anonymous copy of the report?": "A tartalom egy másik kiszolgálóról érkezik. Átviszi a jelentés egy névtelen másolatát?",
|
||||
"The device code is incorrect or no longer valid.": "Az eszköz kódja érvénytelen, vagy már nem érvényes.",
|
||||
"The draft event has been updated": "A piszkozatesemény frissítve lett",
|
||||
"The event has a sign language interpreter": "Az eseménynek van jelnyelvi tolmácsa",
|
||||
"The event has been created as a draft": "Az esemény létre lett hozva piszkozatként",
|
||||
|
@ -1015,6 +1066,8 @@
|
|||
"The post {post} was created by {profile}.": "A(z) {post} bejegyzést {profile} hozta létre.",
|
||||
"The post {post} was deleted by {profile}.": "A(z) {post} bejegyzést {profile} törölte.",
|
||||
"The post {post} was updated by {profile}.": "A(z) {post} bejegyzést {profile} frissítette.",
|
||||
"The provided application was not found.": "A megadott alkalmazás nem található.",
|
||||
"The report contents (eventual comments and event) and the reported profile details will be transmitted to Akismet.": "A jelentés tartalma (a hozzászólások és az esemény) és a jelentett profil részletei el lesznek küldve az Akismetnek.",
|
||||
"The report will be sent to the moderators of your instance. You can explain why you report this content below.": "A jelentés el lesz küldve a példánya moderátorainak. Elmagyarázhatja alább, hogy miért jelenti ezt a tartalmat.",
|
||||
"The selected picture is too heavy. You need to select a file smaller than {size}.": "A kiválasztott kép túl nagy. Egy {size} méretűnél kisebb fájlt kell kiválasztania.",
|
||||
"The technical details of the error can help developers solve the problem more easily. Please add them to your feedback.": "A hiba műszaki részletei segítenek a fejlesztőknek, hogy könnyebben megoldják a problémát. Adja hozzá a visszajelzéséhez.",
|
||||
|
@ -1033,6 +1086,15 @@
|
|||
"This Mobilizon instance and this event organizer allows anonymous participations, but requires validation through email confirmation.": "Ez a Mobilizon példány és ez az eseményszervező megengedi a névtelen részvételeket, de ellenőrzés szükséges e-mailen keresztüli megerősítéssel.",
|
||||
"This URL doesn't seem to be valid": "Ez az URL nem tűnik érvényesnek",
|
||||
"This URL is not supported": "Ez az URL nem támogatott",
|
||||
"This application will be able to access all of your informations and post content. Make sure you only approve applications you trust.": "Ez az alkalmazás hozzá fog férni az összes információjához és a bejegyzései tartalmához. Győződjön meg arról, hogy csak azokat az alkalmazásokat engedélyezi, melyekben megbízik.",
|
||||
"This application will be allowed to delete events": "Az alkalmazás törölheti az eseményeket",
|
||||
"This application will be allowed to delete group posts": "Az alkalmazás törölheti a bejegyzéseket a csoportokból",
|
||||
"This application will be allowed to publish events": "Az alkalmazás közzétehet eseményeket",
|
||||
"This application will be allowed to publish group posts": "Az alkalmazás közzétehet bejegyzéseket a csoportokban",
|
||||
"This application will be allowed to remove uploaded media": "Az alkalmazás törölheti a feltöltött médiafájlokat",
|
||||
"This application will be allowed to update events": "Az alkalmazás frissítheti az eseményeket",
|
||||
"This application will be allowed to update group posts": "Az alkalmazás frissítheti a bejegyzéseket a csoportokban",
|
||||
"This application will be allowed to upload media": "Az alkalmazás tölthet fel médiafájlokat",
|
||||
"This event has been cancelled.": "Ezt az eseményt törölték.",
|
||||
"This event is accessible only through it's link. Be careful where you post this link.": "Ez az esemény csak a hivatkozásán keresztül érhető el. Legyen óvatos, hogy hova küldi be ezt a hivatkozást.",
|
||||
"This group doesn't have a description yet.": "Ennek a csoportnak még nincs leírása.",
|
||||
|
@ -1061,7 +1123,7 @@
|
|||
"This user was not found": "Ez a felhasználó nem található",
|
||||
"This website isn't moderated and the data that you enter will be automatically destroyed every day at 00:01 (Paris timezone).": "Ez a weboldal nincs moderálva, és a beírt adatok automatikusan meg lesznek semmisítve minden nap 00:01-kor (Párizs időzóna).",
|
||||
"This week": "Ez a hét",
|
||||
"This weekend": "Ez a hétvége",
|
||||
"This weekend": "Ezen a hétvégén",
|
||||
"This will delete / anonymize all content (events, comments, messages, participations…) created from this identity.": "Ez törölni vagy névteleníteni fogja az ezzel a személyazonossággal létrehozott összes tartalmat (eseményeket, hozzászólásokat, üzeneteket, részvételeket…).",
|
||||
"Time in your timezone ({timezone})": "Az idő az Ön időzónájában ({timezone})",
|
||||
"Times in your timezone ({timezone})": "Az idők az Ön időzónájában ({timezone})",
|
||||
|
@ -1116,12 +1178,19 @@
|
|||
"Upcoming events from your groups": "Közelgő események a csoportjaitól",
|
||||
"Update": "Frissítés",
|
||||
"Update app": "Alkalmazás frissítése",
|
||||
"Update comments": "Hozzászólások frissítése",
|
||||
"Update discussion title": "Megbeszélés címének frissítése",
|
||||
"Update event {name}": "A(z) {name} esemény frissítése",
|
||||
"Update events": "Események frissítése",
|
||||
"Update group": "Csoport frissítése",
|
||||
"Update group discussions": "Csoport témáinak frissítése",
|
||||
"Update group posts": "Csoport bejegyzéseinek frissítése",
|
||||
"Update group resources": "Csoport erőforrásainak frissítése",
|
||||
"Update my event": "Saját esemény frissítése",
|
||||
"Update post": "Bejegyzés frissítése",
|
||||
"Update profiles": "Profilok frissítése",
|
||||
"Updated": "Frissítve",
|
||||
"Upload media": "Média feltöltése",
|
||||
"Uploaded media size": "Feltöltött média mérete",
|
||||
"Uploaded media total size": "Feltöltött média összmérete",
|
||||
"Use my location": "Saját hely használata",
|
||||
|
@ -1208,6 +1277,7 @@
|
|||
"You can add resources by using the button above.": "A fenti gombbal adhat hozzá erőforrásokat.",
|
||||
"You can add tags by hitting the Enter key or by adding a comma": "Hozzáadhat címkéket az Enter billentyű lenyomásával vagy egy vessző hozzáadásával",
|
||||
"You can pick your timezone into your preferences.": "Kiválaszthatja az időzónát a beállításaiban.",
|
||||
"You can put any arbitrary content in this element. URLs will be clickable.": "Tetszőleges tartalmat tehet ebbe az elembe. A webcím kattintható lesz.",
|
||||
"You can try another search term or drag and drop the marker on the map": "Megpróbálhat egy másik keresési kifejezést, vagy fogd és vidd módon tegye a jelölőt a térképre",
|
||||
"You can't change your password because you are registered through {provider}.": "Nem tudja megváltoztatni a jelszavát, mert {provider} használatával regisztrált.",
|
||||
"You can't use push notifications in this browser.": "Nem tudja használni a leküldéses értesítéseket ebben a böngészőben.",
|
||||
|
@ -1249,6 +1319,7 @@
|
|||
"You moved the resource {resource} into {new_path}.": "Ön áthelyezte a(z) {resource} erőforrást erre a helyre: {new_path}.",
|
||||
"You moved the resource {resource} to the root folder.": "Ön áthelyezte a(z) {resource} erőforrást a gyökérmappába.",
|
||||
"You need to login.": "Be kell jelentkeznie.",
|
||||
"You need to provide the following code to your application. It will only be valid for a few minutes.": "Meg kell adnia a következő kódot az alkalmazásának. Csak néhány percig érvényes.",
|
||||
"You posted a comment on the event {event}.": "Ön hozzászólást küldött a(z) {event} eseményhez.",
|
||||
"You promoted the member {member} to an unknown role.": "Ön előléptette {member} tagot egy ismeretlen szerepre.",
|
||||
"You promoted {member} to administrator.": "Ön előléptette {member} tagot adminisztrátorrá.",
|
||||
|
@ -1275,6 +1346,7 @@
|
|||
"You will find here all the events you have created or of which you are a participant, as well as events organized by groups you follow or are a member of.": "Itt megtalálja az összes eseményt, amelyeket létrehozott vagy amelyeknél Ön résztvevő, illetve az olyan csoportok által szervezett eseményeket, amelyeket Ön követ vagy amelyeknek tagja.",
|
||||
"You will receive notifications about this group's public activity depending on %{notification_settings}.": "Értesítéseket fog kapni ennek a csoportnak a nyilvános tevékenységéről az %{notification_settings} függően.",
|
||||
"You wish to participate to the following event": "Részt kíván venni a következő eseményen",
|
||||
"You'll be able to revoke access for this application in your account settings.": "Az alkalmazás hozzáférését a fiókbeállításokban vonhatja vissza.",
|
||||
"You'll get a weekly recap every Monday for upcoming events, if you have any.": "Heti rövid összegzést fog kapni minden hétfőn a közelgő eseményekről, ha van ilyen.",
|
||||
"You'll need to change the URLs where there were previously entered.": "Meg kell majd változtatnia az URL-eket, ahol korábban meg lettek adva.",
|
||||
"You'll need to transmit the group URL so people may access the group's profile. The group won't be findable in Mobilizon's search or regular search engines.": "Át kell küldenie a csoport URL-jét, hogy az emberek hozzáférhessenek a csoport profiljához. A csoport nem lesz megtalálható a Mobilizon keresőjében vagy a szokásos keresőmotorokban.",
|
||||
|
@ -1285,6 +1357,7 @@
|
|||
"Your account has been validated": "A fiókja ellenőrizve lett",
|
||||
"Your account is being validated": "A fiókja ellenőrizés alatt van",
|
||||
"Your account is nearly ready, {username}": "A fiókja majdnem készen, {username}",
|
||||
"Your application code": "Az alkalmazáskódja",
|
||||
"Your city or region and the radius will only be used to suggest you events nearby. The event radius will consider the administrative center of the area.": "A települése vagy a régiója és a sugár csak a közeli események ajánlásához lesz használva. Az esemény sugara a terület adminisztratív középpontját veszi figyelembe.",
|
||||
"Your current email is {email}. You use it to log in.": "A jelenlegi e-mail-címe {email}. Használja ezt a bejelentkezéshez.",
|
||||
"Your email": "Az e-mail címe",
|
||||
|
@ -1328,6 +1401,7 @@
|
|||
"create an event": "eseményt létrehozni",
|
||||
"default Mobilizon privacy policy": "alapértelmezett Mobilizon adatvédelmi irányelv",
|
||||
"default Mobilizon terms": "alapértelmezett Mobilizon használati feltételek",
|
||||
"detail": " ",
|
||||
"e.g. 10 Rue Jangot": "például Budapest, I. kerület",
|
||||
"e.g. Accessibility, Twitch, PeerTube": "például akadálymentesítés, Twitch, PeerTube",
|
||||
"e.g. Nantes, Berlin, Cork, …": "például Nantes, Berlin, Cork…",
|
||||
|
@ -1351,6 +1425,7 @@
|
|||
"return to the homepage": "visszatérhet a kezdőlapra",
|
||||
"terms of service": "szolgáltatás feltételeit",
|
||||
"tool designed to serve you": "eszköz, amelyet arra terveztek, hogy Önt szolgálja",
|
||||
"translation": " ",
|
||||
"with another identity…": "egy másik személyazonossággal…",
|
||||
"your notification settings": "értesítési beállításaitól",
|
||||
"{'@'}{username}": "{'@'}{username}",
|
||||
|
|
1631
src/i18n/sv.json
1631
src/i18n/sv.json
File diff suppressed because it is too large
Load diff
|
@ -54,15 +54,14 @@
|
|||
>
|
||||
</o-field>
|
||||
<o-field
|
||||
:label="t('Domain')"
|
||||
:label="t('Domain or instance name')"
|
||||
label-for="domain-filter"
|
||||
class="flex-auto"
|
||||
>
|
||||
<o-input
|
||||
id="domain-filter"
|
||||
:placeholder="t('mobilizon-instance.tld')"
|
||||
:value="filterDomain"
|
||||
@input="debouncedUpdateDomainFilter"
|
||||
v-model="filterDomain"
|
||||
/>
|
||||
</o-field>
|
||||
</div>
|
||||
|
@ -223,7 +222,6 @@ import { Paginate } from "@/types/paginate";
|
|||
import RouteName from "../../router/name";
|
||||
import { IInstance } from "@/types/instance.model";
|
||||
import EmptyContent from "@/components/Utils/EmptyContent.vue";
|
||||
import debounce from "lodash/debounce";
|
||||
import {
|
||||
InstanceFilterFollowStatus,
|
||||
InstanceFollowStatus,
|
||||
|
@ -254,12 +252,16 @@ const followStatus = useRouteQuery(
|
|||
|
||||
const { result: instancesResult } = useQuery<{
|
||||
instances: Paginate<IInstance>;
|
||||
}>(INSTANCES, () => ({
|
||||
page: instancePage.value,
|
||||
limit: INSTANCES_PAGE_LIMIT,
|
||||
filterDomain: filterDomain.value,
|
||||
filterFollowStatus: followStatus.value,
|
||||
}));
|
||||
}>(
|
||||
INSTANCES,
|
||||
() => ({
|
||||
page: instancePage.value,
|
||||
limit: INSTANCES_PAGE_LIMIT,
|
||||
filterDomain: filterDomain.value,
|
||||
filterFollowStatus: followStatus.value,
|
||||
}),
|
||||
{ debounce: 500 }
|
||||
);
|
||||
|
||||
const instances = computed(() => instancesResult.value?.instances);
|
||||
|
||||
|
@ -276,13 +278,6 @@ const newRelayAddress = ref("");
|
|||
|
||||
// relayFollowers: Paginate<IFollower> = { elements: [], total: 0 };
|
||||
|
||||
const updateDomainFilter = (event: InputEvent) => {
|
||||
const newValue = (event.target as HTMLInputElement).value;
|
||||
filterDomain.value = newValue;
|
||||
};
|
||||
|
||||
const debouncedUpdateDomainFilter = debounce(updateDomainFilter, 500);
|
||||
|
||||
const hasFilter = computed((): boolean => {
|
||||
return (
|
||||
followStatus.value !== InstanceFilterFollowStatus.ALL ||
|
||||
|
|
|
@ -1087,7 +1087,10 @@ const physicalAddress = computed((): Address | null => {
|
|||
});
|
||||
|
||||
const ableToReport = computed((): boolean => {
|
||||
return anonymousReportsConfig.value?.allowed === true;
|
||||
return (
|
||||
currentActor.value?.id !== undefined ||
|
||||
anonymousReportsConfig.value?.allowed === true
|
||||
);
|
||||
});
|
||||
|
||||
const organizedEvents = computed((): Paginate<IEvent> => {
|
||||
|
|
|
@ -179,7 +179,7 @@ defmodule Mix.Tasks.Mobilizon.Actors.NewTest do
|
|||
assert %Actor{name: @group_name, preferred_username: @group_username, id: group_id} =
|
||||
Actors.get_group_by_title(@group_username)
|
||||
|
||||
assert Actors.is_administrator?(admin_id, group_id)
|
||||
assert Actors.administrator?(admin_id, group_id)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue