summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLain Soykaf <lain@soykaf.club>2021-01-22 15:29:43 +0100
committerLain Soykaf <lain@soykaf.club>2021-01-22 15:29:43 +0100
commit821b36f06ce1a12ef16efb57a44ba7781cbbf4fb (patch)
tree4d4783589e0663197aa84473e2dec2f1befe766d
parent42e495df2b8d72365e22f8be708051130bc81973 (diff)
Groups: Add basic groups.
-rw-r--r--lib/pleroma/group.ex74
-rw-r--r--lib/pleroma/user.ex6
-rw-r--r--priv/repo/migrations/20210113150220_create_groups.exs17
-rw-r--r--test/pleroma/group_test.exs36
4 files changed, 133 insertions, 0 deletions
diff --git a/lib/pleroma/group.ex b/lib/pleroma/group.ex
new file mode 100644
index 000000000..6cc208f15
--- /dev/null
+++ b/lib/pleroma/group.ex
@@ -0,0 +1,74 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Group do
+ use Ecto.Schema
+
+ import Ecto.Changeset
+
+ alias Pleroma.User
+ alias Pleroma.Repo
+ alias Pleroma.Web
+ alias Pleroma.EctoType.ActivityPub.ObjectValidators
+
+ @moduledoc """
+ Groups contain all the additional information about a group that's not stored
+ in the user table.
+
+ Concepts:
+
+ - Groups have an owner
+ - Groups have members, invited by the owner.
+ """
+
+ @type t :: %__MODULE__{}
+ @primary_key {:id, FlakeId.Ecto.CompatType, autogenerate: true}
+
+ schema "groups" do
+ belongs_to(:user, User, type: FlakeId.Ecto.CompatType)
+ belongs_to(:owner, User, type: FlakeId.Ecto.CompatType, foreign_key: :owner_id)
+
+ field(:members, {:array, ObjectValidators.ObjectID})
+ field(:name, :string)
+ field(:description, :string)
+ field(:members_collection, :string)
+
+ timestamps()
+ end
+
+ @spec create(map()) :: {:ok, t()} | {:error, Ecto.Changeset.t()}
+ def create(params) do
+ with {:ok, user} <- generate_user() do
+ %__MODULE__{user_id: user.id, members_collection: "#{user.ap_id}/members"}
+ |> changeset(params)
+ |> Repo.insert()
+ end
+ end
+
+ defp generate_ap_id(id) do
+ "#{Web.base_url()}/groups/#{id}"
+ end
+
+ defp generate_user() do
+ id = Ecto.UUID.generate()
+ ap_id = generate_ap_id(id)
+
+ %{
+ ap_id: ap_id,
+ name: id,
+ nickname: id,
+ follower_address: "#{ap_id}/followers",
+ following_address: "#{ap_id}/following",
+ local: true
+ }
+ |> User.group_changeset()
+ |> Repo.insert()
+ end
+
+ def changeset(struct, params) do
+ struct
+ |> cast(params, [:user_id, :owner_id, :name, :description, :members_collection])
+ |> validate_required([:user_id, :owner_id, :members_collection])
+ end
+end
diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex
index 2aeacf816..3da658950 100644
--- a/lib/pleroma/user.ex
+++ b/lib/pleroma/user.ex
@@ -407,6 +407,12 @@ defmodule Pleroma.User do
defp fix_follower_address(params), do: params
+ def group_changeset(struct \\ %User{actor_type: "Group"}, params) do
+ struct
+ |> cast(params, [:ap_id, :nickname, :name, :follower_address, :following_address, :local])
+ |> validate_required([:ap_id, :nickname, :name, :follower_address, :following_address, :local])
+ end
+
def remote_user_changeset(struct \\ %User{local: false}, params) do
bio_limit = Config.get([:instance, :user_bio_length], 5000)
name_limit = Config.get([:instance, :user_name_length], 100)
diff --git a/priv/repo/migrations/20210113150220_create_groups.exs b/priv/repo/migrations/20210113150220_create_groups.exs
new file mode 100644
index 000000000..642326d51
--- /dev/null
+++ b/priv/repo/migrations/20210113150220_create_groups.exs
@@ -0,0 +1,17 @@
+defmodule Pleroma.Repo.Migrations.CreateGroups do
+ use Ecto.Migration
+
+ def change do
+ create table(:groups, primary_key: false) do
+ add(:id, :uuid, primary_key: true)
+ 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(:members, {:array, :string}, default: [])
+ add(:name, :text)
+ add(:description, :text)
+ add(:members_collection, :text)
+
+ timestamps()
+ end
+ end
+end
diff --git a/test/pleroma/group_test.exs b/test/pleroma/group_test.exs
new file mode 100644
index 000000000..f73abd237
--- /dev/null
+++ b/test/pleroma/group_test.exs
@@ -0,0 +1,36 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.GroupTest do
+ use Pleroma.DataCase, async: true
+
+ alias Pleroma.Group
+ alias Pleroma.Repo
+
+ import Pleroma.Factory
+
+ test "a user can create a group" do
+ user = insert(:user)
+ {:ok, group} = Group.create(%{owner_id: user.id, name: "cofe", description: "corndog"})
+ group = Repo.preload(group, :user)
+
+ assert group.user.actor_type == "Group"
+ assert group.owner_id == user.id
+ assert group.name == "cofe"
+ assert group.description == "corndog"
+
+ # Deleting the owner does not delete the group, just orphans it
+ Repo.delete(user)
+
+ group =
+ Repo.get(Group, group.id)
+ |> Repo.preload(:user)
+
+ assert group.owner_id == nil
+
+ # Deleting the group user deletes the group
+ Repo.delete(group.user)
+ refute Repo.get(Group, group.id)
+ end
+end