First
[anni] / lib / pleroma / web / api_spec / operations / subscription_operation.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.ApiSpec.SubscriptionOperation do
6   alias OpenApiSpex.Operation
7   alias OpenApiSpex.Schema
8   alias Pleroma.Web.ApiSpec.Helpers
9   alias Pleroma.Web.ApiSpec.Schemas.ApiError
10   alias Pleroma.Web.ApiSpec.Schemas.BooleanLike
11   alias Pleroma.Web.ApiSpec.Schemas.PushSubscription
12
13   def open_api_operation(action) do
14     operation = String.to_existing_atom("#{action}_operation")
15     apply(__MODULE__, operation, [])
16   end
17
18   def create_operation do
19     %Operation{
20       tags: ["Push subscriptions"],
21       summary: "Subscribe to push notifications",
22       description:
23         "Add a Web Push API subscription to receive notifications. Each access token can have one push subscription. If you create a new subscription, the old subscription is deleted.",
24       operationId: "SubscriptionController.create",
25       security: [%{"oAuth" => ["push"]}],
26       requestBody: Helpers.request_body("Parameters", create_request(), required: true),
27       responses: %{
28         200 => Operation.response("Push subscription", "application/json", PushSubscription),
29         400 => Operation.response("Error", "application/json", ApiError),
30         403 => Operation.response("Error", "application/json", ApiError)
31       }
32     }
33   end
34
35   def show_operation do
36     %Operation{
37       tags: ["Push subscriptions"],
38       summary: "Get current subscription",
39       description: "View the PushSubscription currently associated with this access token.",
40       operationId: "SubscriptionController.show",
41       security: [%{"oAuth" => ["push"]}],
42       responses: %{
43         200 => Operation.response("Push subscription", "application/json", PushSubscription),
44         403 => Operation.response("Error", "application/json", ApiError),
45         404 => Operation.response("Error", "application/json", ApiError)
46       }
47     }
48   end
49
50   def update_operation do
51     %Operation{
52       tags: ["Push subscriptions"],
53       summary: "Change types of notifications",
54       description:
55         "Updates the current push subscription. Only the data part can be updated. To change fundamentals, a new subscription must be created instead.",
56       operationId: "SubscriptionController.update",
57       security: [%{"oAuth" => ["push"]}],
58       requestBody: Helpers.request_body("Parameters", update_request(), required: true),
59       responses: %{
60         200 => Operation.response("Push subscription", "application/json", PushSubscription),
61         403 => Operation.response("Error", "application/json", ApiError)
62       }
63     }
64   end
65
66   def delete_operation do
67     %Operation{
68       tags: ["Push subscriptions"],
69       summary: "Remove current subscription",
70       description: "Removes the current Web Push API subscription.",
71       operationId: "SubscriptionController.delete",
72       security: [%{"oAuth" => ["push"]}],
73       responses: %{
74         200 => Operation.response("Empty object", "application/json", %Schema{type: :object}),
75         403 => Operation.response("Error", "application/json", ApiError),
76         404 => Operation.response("Error", "application/json", ApiError)
77       }
78     }
79   end
80
81   defp create_request do
82     %Schema{
83       title: "SubscriptionCreateRequest",
84       description: "POST body for creating a push subscription",
85       type: :object,
86       properties: %{
87         subscription: %Schema{
88           type: :object,
89           properties: %{
90             endpoint: %Schema{
91               type: :string,
92               description: "Endpoint URL that is called when a notification event occurs."
93             },
94             keys: %Schema{
95               type: :object,
96               properties: %{
97                 p256dh: %Schema{
98                   type: :string,
99                   description:
100                     "User agent public key. Base64 encoded string of public key of ECDH key using `prime256v1` curve."
101                 },
102                 auth: %Schema{
103                   type: :string,
104                   description: "Auth secret. Base64 encoded string of 16 bytes of random data."
105                 }
106               },
107               required: [:p256dh, :auth]
108             }
109           },
110           required: [:endpoint, :keys]
111         },
112         data: %Schema{
113           nullable: true,
114           type: :object,
115           properties: %{
116             alerts: %Schema{
117               nullable: true,
118               type: :object,
119               properties: %{
120                 follow: %Schema{
121                   allOf: [BooleanLike],
122                   nullable: true,
123                   description: "Receive follow notifications?"
124                 },
125                 favourite: %Schema{
126                   allOf: [BooleanLike],
127                   nullable: true,
128                   description: "Receive favourite notifications?"
129                 },
130                 reblog: %Schema{
131                   allOf: [BooleanLike],
132                   nullable: true,
133                   description: "Receive reblog notifications?"
134                 },
135                 mention: %Schema{
136                   allOf: [BooleanLike],
137                   nullable: true,
138                   description: "Receive mention notifications?"
139                 },
140                 poll: %Schema{
141                   allOf: [BooleanLike],
142                   nullable: true,
143                   description: "Receive poll notifications?"
144                 },
145                 "pleroma:chat_mention": %Schema{
146                   allOf: [BooleanLike],
147                   nullable: true,
148                   description: "Receive chat notifications?"
149                 },
150                 "pleroma:emoji_reaction": %Schema{
151                   allOf: [BooleanLike],
152                   nullable: true,
153                   description: "Receive emoji reaction notifications?"
154                 }
155               }
156             }
157           }
158         }
159       },
160       required: [:subscription],
161       example: %{
162         "subscription" => %{
163           "endpoint" => "https://example.com/example/1234",
164           "keys" => %{
165             "auth" => "8eDyX_uCN0XRhSbY5hs7Hg==",
166             "p256dh" =>
167               "BCIWgsnyXDv1VkhqL2P7YRBvdeuDnlwAPT2guNhdIoW3IP7GmHh1SMKPLxRf7x8vJy6ZFK3ol2ohgn_-0yP7QQA="
168           }
169         },
170         "data" => %{
171           "alerts" => %{
172             "follow" => true,
173             "mention" => true,
174             "poll" => false
175           }
176         }
177       }
178     }
179   end
180
181   defp update_request do
182     %Schema{
183       title: "SubscriptionUpdateRequest",
184       type: :object,
185       properties: %{
186         data: %Schema{
187           nullable: true,
188           type: :object,
189           properties: %{
190             alerts: %Schema{
191               nullable: true,
192               type: :object,
193               properties: %{
194                 follow: %Schema{
195                   allOf: [BooleanLike],
196                   nullable: true,
197                   description: "Receive follow notifications?"
198                 },
199                 favourite: %Schema{
200                   allOf: [BooleanLike],
201                   nullable: true,
202                   description: "Receive favourite notifications?"
203                 },
204                 reblog: %Schema{
205                   allOf: [BooleanLike],
206                   nullable: true,
207                   description: "Receive reblog notifications?"
208                 },
209                 mention: %Schema{
210                   allOf: [BooleanLike],
211                   nullable: true,
212                   description: "Receive mention notifications?"
213                 },
214                 poll: %Schema{
215                   allOf: [BooleanLike],
216                   nullable: true,
217                   description: "Receive poll notifications?"
218                 },
219                 "pleroma:chat_mention": %Schema{
220                   allOf: [BooleanLike],
221                   nullable: true,
222                   description: "Receive chat notifications?"
223                 },
224                 "pleroma:emoji_reaction": %Schema{
225                   allOf: [BooleanLike],
226                   nullable: true,
227                   description: "Receive emoji reaction notifications?"
228                 }
229               }
230             }
231           }
232         }
233       },
234       example: %{
235         "data" => %{
236           "alerts" => %{
237             "follow" => true,
238             "favourite" => true,
239             "reblog" => true,
240             "mention" => true,
241             "poll" => true
242           }
243         }
244       }
245     }
246   end
247 end