Groups: Add basic groups.

This commit is contained in:
Lain Soykaf 2021-01-22 15:29:43 +01:00
parent 42e495df2b
commit 821b36f06c
4 changed files with 133 additions and 0 deletions

74
lib/pleroma/group.ex Normal file
View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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