ce33051428e179411cdd4d0415ff4198c9cf398a
[anni] / lib / pleroma / web / activity_pub / object_validators / question_validator.ex
1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
4
5 defmodule Pleroma.Web.ActivityPub.ObjectValidators.QuestionValidator do
6   use Ecto.Schema
7
8   alias Pleroma.EctoType.ActivityPub.ObjectValidators
9   alias Pleroma.Web.ActivityPub.ObjectValidators.CommonFixes
10   alias Pleroma.Web.ActivityPub.ObjectValidators.CommonValidations
11   alias Pleroma.Web.ActivityPub.ObjectValidators.QuestionOptionsValidator
12   alias Pleroma.Web.ActivityPub.Transmogrifier
13
14   import Ecto.Changeset
15
16   @primary_key false
17   @derive Jason.Encoder
18
19   # Extends from NoteValidator
20   embedded_schema do
21     quote do
22       unquote do
23         import Elixir.Pleroma.Web.ActivityPub.ObjectValidators.CommonFields
24         message_fields()
25         object_fields()
26         status_object_fields()
27       end
28     end
29
30     field(:closed, ObjectValidators.DateTime)
31     field(:voters, {:array, ObjectValidators.ObjectID}, default: [])
32     embeds_many(:anyOf, QuestionOptionsValidator)
33     embeds_many(:oneOf, QuestionOptionsValidator)
34   end
35
36   def cast_and_apply(data) do
37     data
38     |> cast_data
39     |> apply_action(:insert)
40   end
41
42   def cast_and_validate(data) do
43     data
44     |> cast_data()
45     |> validate_data()
46   end
47
48   def cast_data(data) do
49     %__MODULE__{}
50     |> changeset(data)
51   end
52
53   defp fix_closed(data) do
54     cond do
55       is_binary(data["closed"]) -> data
56       is_binary(data["endTime"]) -> Map.put(data, "closed", data["endTime"])
57       true -> Map.drop(data, ["closed"])
58     end
59   end
60
61   defp fix(data) do
62     data
63     |> CommonFixes.fix_actor()
64     |> CommonFixes.fix_object_defaults()
65     |> Transmogrifier.fix_emoji()
66     |> fix_closed()
67   end
68
69   def changeset(struct, data) do
70     data = fix(data)
71
72     struct
73     |> cast(data, __schema__(:fields) -- [:anyOf, :oneOf, :attachment, :tag])
74     |> cast_embed(:attachment)
75     |> cast_embed(:anyOf)
76     |> cast_embed(:oneOf)
77     |> cast_embed(:tag)
78   end
79
80   defp validate_data(data_cng) do
81     data_cng
82     |> validate_inclusion(:type, ["Question"])
83     |> validate_required([:id, :actor, :attributedTo, :type, :context])
84     |> CommonValidations.validate_any_presence([:cc, :to])
85     |> CommonValidations.validate_fields_match([:actor, :attributedTo])
86     |> CommonValidations.validate_actor_presence()
87     |> CommonValidations.validate_any_presence([:oneOf, :anyOf])
88     |> CommonValidations.validate_host_match()
89   end
90 end