Groups: Basic group validation.

This commit is contained in:
Lain Soykaf 2021-01-28 09:33:30 +01:00
parent 633d0286b3
commit d18ba133b2
10 changed files with 173 additions and 1 deletions

View File

@ -92,4 +92,15 @@ defmodule Pleroma.Group do
{:ok, group} {:ok, group}
end end
end end
@spec get_for_object(map()) :: t() | nil
def get_for_object(%{"type" => "Group", "id" => id}) do
with %User{} = user <- User.get_cached_by_ap_id(id),
group <- Repo.preload(user, :group).group do
group
end
end
def get_for_object(%{"type" => "Create", "object" => object}), do: get_for_object(object)
def get_for_object(_), do: nil
end end

View File

@ -18,6 +18,7 @@ defmodule Pleroma.User do
alias Pleroma.Emoji alias Pleroma.Emoji
alias Pleroma.FollowingRelationship alias Pleroma.FollowingRelationship
alias Pleroma.Formatter alias Pleroma.Formatter
alias Pleroma.Group
alias Pleroma.HTML alias Pleroma.HTML
alias Pleroma.Keys alias Pleroma.Keys
alias Pleroma.MFA alias Pleroma.MFA
@ -209,6 +210,9 @@ defmodule Pleroma.User do
on_replace: :delete on_replace: :delete
) )
# Some `users` are actually groups. In this case, they can have a corresponding `Group`
has_one(:group, Group)
timestamps() timestamps()
end end

View File

@ -12,6 +12,7 @@ defmodule Pleroma.Web.ActivityPub.Builder do
alias Pleroma.Emoji alias Pleroma.Emoji
alias Pleroma.Object alias Pleroma.Object
alias Pleroma.User alias Pleroma.User
alias Pleroma.Web
alias Pleroma.Web.ActivityPub.Relay alias Pleroma.Web.ActivityPub.Relay
alias Pleroma.Web.ActivityPub.Utils alias Pleroma.Web.ActivityPub.Utils
alias Pleroma.Web.ActivityPub.Visibility alias Pleroma.Web.ActivityPub.Visibility
@ -105,6 +106,30 @@ defmodule Pleroma.Web.ActivityPub.Builder do
}, []} }, []}
end end
def group(owner, name \\ nil, description \\ nil) do
id = Ecto.UUID.generate()
ap_id = "#{Web.base_url()}/groups/#{id}"
{:ok,
%{
"id" => ap_id,
"type" => "Group",
"name" => name,
"summary" => description,
"following" => "#{ap_id}/following",
"followers" => "#{ap_id}/followers",
"members" => "#{ap_id}/members",
# attributedTo? owner? admin?
"attributedTo" => owner.ap_id
}, []}
end
def create_group(owner, params \\ %{}) do
with {:ok, group, _} <- group(owner, params[:name], params[:description]) do
create(owner, group, [])
end
end
def create(actor, object, recipients) do def create(actor, object, recipients) do
context = context =
if is_map(object) do if is_map(object) do

View File

@ -29,6 +29,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidator do
alias Pleroma.Web.ActivityPub.ObjectValidators.EmojiReactValidator alias Pleroma.Web.ActivityPub.ObjectValidators.EmojiReactValidator
alias Pleroma.Web.ActivityPub.ObjectValidators.EventValidator alias Pleroma.Web.ActivityPub.ObjectValidators.EventValidator
alias Pleroma.Web.ActivityPub.ObjectValidators.FollowValidator alias Pleroma.Web.ActivityPub.ObjectValidators.FollowValidator
alias Pleroma.Web.ActivityPub.ObjectValidators.GroupValidator
alias Pleroma.Web.ActivityPub.ObjectValidators.LikeValidator alias Pleroma.Web.ActivityPub.ObjectValidators.LikeValidator
alias Pleroma.Web.ActivityPub.ObjectValidators.QuestionValidator alias Pleroma.Web.ActivityPub.ObjectValidators.QuestionValidator
alias Pleroma.Web.ActivityPub.ObjectValidators.UndoValidator alias Pleroma.Web.ActivityPub.ObjectValidators.UndoValidator
@ -37,6 +38,16 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidator do
@impl true @impl true
def validate(object, meta) def validate(object, meta)
def validate(%{"type" => "Group"} = object, meta) do
with {:ok, object} <-
object
|> GroupValidator.cast_and_validate()
|> Ecto.Changeset.apply_action(:insert) do
object = stringify_keys(object)
{:ok, object, meta}
end
end
def validate(%{"type" => type} = object, meta) def validate(%{"type" => type} = object, meta)
when type in ~w[Accept Reject] do when type in ~w[Accept Reject] do
with {:ok, object} <- with {:ok, object} <-

View File

@ -0,0 +1,40 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.ObjectValidators.GroupValidator do
use Ecto.Schema
alias Pleroma.EctoType.ActivityPub.ObjectValidators
import Ecto.Changeset
@primary_key false
embedded_schema do
field(:id, ObjectValidators.ObjectID, primary_key: true)
field(:type, :string)
end
def cast_and_validate(data) do
data
|> cast_data()
|> validate_data()
end
def cast_data(data) do
%__MODULE__{}
|> changeset(data)
end
def changeset(struct, data) do
struct
|> cast(data, __schema__(:fields))
end
def validate_data(data_cng) do
data_cng
|> validate_inclusion(:type, ["Group"])
|> validate_required([:id])
end
end

View File

@ -30,6 +30,13 @@ defmodule Pleroma.Web.CommonAPI do
end end
end end
def create_group(user, params) do
with {:ok, group_data, _} <- Builder.create_group(user, params),
{:ok, group, _} <- Pipeline.common_pipeline(group_data, local: true) do
{:ok, group}
end
end
def post_chat_message(%User{} = user, %User{} = recipient, content, opts \\ []) do def post_chat_message(%User{} = user, %User{} = recipient, content, opts \\ []) do
with maybe_attachment <- opts[:media_id] && Object.get_by_id(opts[:media_id]), with maybe_attachment <- opts[:media_id] && Object.get_by_id(opts[:media_id]),
:ok <- validate_chat_content_length(content, !!maybe_attachment), :ok <- validate_chat_content_length(content, !!maybe_attachment),

View File

@ -6,7 +6,6 @@ defmodule Pleroma.Repo.Migrations.CreateGroups do
add(:id, :uuid, primary_key: true) add(:id, :uuid, primary_key: true)
add(:user_id, references(:users, type: :uuid, on_delete: :delete_all), null: false) add(:user_id, references(:users, type: :uuid, on_delete: :delete_all), null: false)
add(:owner_id, references(:users, type: :uuid, on_delete: :nilify_all)) add(:owner_id, references(:users, type: :uuid, on_delete: :nilify_all))
add(:members, {:array, :string}, default: [])
add(:name, :text) add(:name, :text)
add(:description, :text) add(:description, :text)
add(:members_collection, :text) add(:members_collection, :text)

View File

@ -10,6 +10,32 @@ defmodule Pleroma.GroupTest do
import Pleroma.Factory import Pleroma.Factory
test "get_for_object/1 gets a group based on the group object or the create activity" do
user = insert(:user)
{:ok, group} = Group.create(%{owner_id: user.id, name: "cofe", description: "corndog"})
group = Repo.preload(group, :user)
group_object = %{
"id" => group.user.ap_id,
"type" => "Group"
}
assert group.id == Group.get_for_object(group_object).id
# Same works if wrapped in a 'create'
group_create = %{
"type" => "Create",
"object" => group_object
}
assert group.id == Group.get_for_object(group_create).id
# Nil for nonsense
assert nil == Group.get_for_object(%{"nothing" => "PS4 games"})
end
test "a user can create a group" do test "a user can create a group" do
user = insert(:user) user = insert(:user)
{:ok, group} = Group.create(%{owner_id: user.id, name: "cofe", description: "corndog"}) {:ok, group} = Group.create(%{owner_id: user.id, name: "cofe", description: "corndog"})

View File

@ -0,0 +1,24 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.ObjectValidators.GroupValidationTest do
use Pleroma.DataCase, async: true
import Pleroma.Factory
alias Pleroma.Web.ActivityPub.Builder
alias Pleroma.Web.ActivityPub.ObjectValidator
describe "Group objects" do
test "it validates a group" do
user = insert(:user)
{:ok, group_data, []} = Builder.group(user, "a group", "a description")
{:ok, group, _} = ObjectValidator.validate(group_data, [])
assert group
end
end
end

View File

@ -0,0 +1,25 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.CommonAPI.GroupMessagingTest do
use Pleroma.DataCase
import Pleroma.Factory
alias Pleroma.Group
alias Pleroma.Web.CommonAPI
describe "Group chats" do
test "local chat" do
user = insert(:user)
{:ok, group_creation_activity} =
CommonAPI.create_group(user, %{name: "cofe", description: "for cofe enthusiasts"})
group = Group.get_for_object(group_creation_activity)
assert group
end
end
end