event editing?

Signed-off-by: marcin mikołajczak <git@mkljczk.pl>
This commit is contained in:
marcin mikołajczak 2022-09-27 23:56:20 +02:00
parent daccdc179c
commit f7d9f42243
7 changed files with 170 additions and 18 deletions

View file

@ -34,6 +34,23 @@ def create_operation do
}
end
def update_operation do
%Operation{
tags: ["Event actions"],
summary: "Update event",
description: "Change the content of an event",
operationId: "PleromaAPI.EventController.update",
security: [%{"oAuth" => ["write"]}],
parameters: [id_param()],
requestBody: request_body("Parameters", update_request(), required: true),
responses: %{
200 => event_response(),
403 => Operation.response("Forbidden", "application/json", ApiError),
404 => Operation.response("Not Found", "application/json", ApiError)
}
}
end
def participations_operation do
%Operation{
tags: ["Event actions"],
@ -217,6 +234,50 @@ defp create_request do
}
end
defp update_request do
%Schema{
title: "EventUpdateRequest",
type: :object,
properties: %{
name: %Schema{
type: :string,
description: "Name of the event."
},
status: %Schema{
type: :string,
nullable: true,
description: "Text description of the event."
},
banner_id: %Schema{
nullable: true,
type: :string,
description: "Attachment id to be attached as banner."
},
start_time: %Schema{
type: :string,
format: :"date-time",
description: "Start time."
},
end_time: %Schema{
type: :string,
format: :"date-time",
description: "End time."
},
location_id: %Schema{
type: :string,
description: "Location ID from geospatial provider",
nullable: true
}
},
example: %{
"name" => "Updated event",
"status" => "We had to reschedule the event.",
"start_time" => "2022-02-22T22:00:00.000Z",
"end_time" => "2022-02-22T23:00:00.000Z"
}
}
end
defp event_response do
Operation.response(
"Status",

View file

@ -743,4 +743,39 @@ def event(user, data, location \\ nil) do
ActivityPub.create(draft.changes)
end
end
def update_event(user, orig_activity, changes) do
with orig_object <- Object.normalize(orig_activity),
{:ok, new_object} <- make_update_event_data(user, orig_object, changes),
{:ok, update_data, _} <- Builder.update(user, new_object),
{:ok, update, _} <- Pipeline.common_pipeline(update_data, local: true) do
{:ok, update}
else
_ -> {:error, nil}
end
end
defp make_update_event_data(user, orig_object, changes) do
kept_params = %{
visibility: Visibility.get_visibility(orig_object),
in_reply_to_id:
with replied_id when is_binary(replied_id) <- orig_object.data["inReplyTo"],
%Activity{id: activity_id} <- Activity.get_create_by_object_ap_id(replied_id) do
activity_id
else
_ -> nil
end
}
params = Map.merge(changes, kept_params)
with {:ok, draft} <- ActivityDraft.event(user, params) do
change =
Object.Updater.make_update_object_data(orig_object.data, draft.object, Utils.make_date())
{:ok, change}
else
_ -> {:error, nil}
end
end
end

View file

@ -135,7 +135,13 @@ defp event_object(draft) do
"location_id" => draft.location_id,
"location_provider" => draft.location_provider,
"startTime" => draft.start_time,
"endTime" => draft.end_time
"endTime" => draft.end_time,
"source" => %{
"content" => draft.status,
"mediaType" => Utils.get_content_type(draft.params[:content_type])
},
"generator" => draft.params[:generator],
"content_type" => draft.params[:content_type],
}
%__MODULE__{draft | object: object}

View file

@ -21,7 +21,6 @@ defmodule Pleroma.Web.MastodonAPI.StatusController do
alias Pleroma.Web.CommonAPI
alias Pleroma.Web.MastodonAPI.AccountView
alias Pleroma.Web.MastodonAPI.ScheduledActivityView
alias Pleroma.Web.OAuth.Token
alias Pleroma.Web.Plugs.OAuthScopesPlug
alias Pleroma.Web.Plugs.RateLimiter
@ -101,6 +100,8 @@ defmodule Pleroma.Web.MastodonAPI.StatusController do
plug(RateLimiter, [name: :statuses_actions] when action in @rate_limited_status_actions)
plug(Pleroma.Web.Plugs.SetApplicationPlug, [] when action in [:create, :update])
action_fallback(Pleroma.Web.MastodonAPI.FallbackController)
defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.StatusOperation
@ -140,8 +141,9 @@ def create(
)
when not is_nil(scheduled_at) do
params =
Map.put(params, :in_reply_to_status_id, params[:in_reply_to_id])
|> put_application(conn)
params
|> Map.put(:in_reply_to_status_id, params[:in_reply_to_id])
|> Map.put(:application, conn.assigns.application)
attrs = %{
params: Map.new(params, fn {key, value} -> {to_string(key), value} end),
@ -166,8 +168,9 @@ def create(
# Creates a regular status
def create(%{assigns: %{user: user}, body_params: %{status: _} = params} = conn, _) do
params =
Map.put(params, :in_reply_to_status_id, params[:in_reply_to_id])
|> put_application(conn)
params
|> Map.put(:in_reply_to_status_id, params[:in_reply_to_id])
|> Map.put(:application, conn.assigns.application)
with {:ok, activity} <- CommonAPI.post(user, params) do
try_render(conn, "show.json",
@ -231,7 +234,7 @@ def update(%{assigns: %{user: user}, body_params: body_params} = conn, %{id: id}
{_, true} <- {:is_create, activity.data["type"] == "Create"},
actor <- Activity.user_actor(activity),
{_, true} <- {:own_status, actor.id == user.id},
changes <- body_params |> put_application(conn),
changes <- body_params |> Map.put(:application, conn.assigns.application),
{_, {:ok, _update_activity}} <- {:pipeline, CommonAPI.update(user, activity, changes)},
{_, %Activity{}} = {_, activity} <- {:refetched, Activity.get_by_id_with_object(id)} do
try_render(conn, "show.json",
@ -484,15 +487,4 @@ def bookmarks(%{assigns: %{user: user}} = conn, params) do
as: :activity
)
end
defp put_application(params, %{assigns: %{token: %Token{user: %User{} = user} = token}} = _conn) do
if user.disclose_client do
%{client_name: client_name, website: website} = Repo.preload(token, :app).app
Map.put(params, :generator, %{type: "Application", name: client_name, url: website})
else
Map.put(params, :generator, nil)
end
end
defp put_application(params, _), do: Map.put(params, :generator, nil)
end

View file

@ -48,6 +48,7 @@ defmodule Pleroma.Web.PleromaAPI.EventController do
%{scopes: ["write"]}
when action in [
:create,
:update,
:authorize_participation_request,
:reject_participation_request,
:join,
@ -67,6 +68,8 @@ defmodule Pleroma.Web.PleromaAPI.EventController do
when action in [:export_ics]
)
plug(Pleroma.Web.Plugs.SetApplicationPlug, [] when action in [:create, :update])
defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.PleromaEventOperation
def create(%{assigns: %{user: user}, body_params: params} = conn, _) do
@ -96,6 +99,32 @@ def create(%{assigns: %{user: user}, body_params: params} = conn, _) do
end
end
@doc "PUT /api/v1/statuses/:id"
def update(%{assigns: %{user: user}, body_params: body_params} = conn, %{id: id} = params) do
with {_, %Activity{}} = {_, activity} <- {:activity, Activity.get_by_id_with_object(id)},
{_, true} <- {:visible, Visibility.visible_for_user?(activity, user)},
{_, true} <- {:is_create, activity.data["type"] == "Create"},
actor <- Activity.user_actor(activity),
{_, true} <- {:own_status, actor.id == user.id},
changes <- body_params |> Map.put(:application, conn.assigns.application),
{_, {:ok, _update_activity}} <-
{:pipeline, CommonAPI.update_event(user, activity, changes)},
{_, %Activity{}} = {_, activity} <- {:refetched, Activity.get_by_id_with_object(id)} do
conn
|> put_view(StatusView)
|> try_render("show.json",
activity: activity,
for: user,
with_direct_conversation_id: true,
with_muted: Map.get(params, :with_muted, false)
)
else
{:own_status, _} -> {:error, :forbidden}
{:pipeline, e} -> {:error, :internal_server_error}
_ -> {:error, :not_found}
end
end
defp get_location(%{location_id: location_id}) when is_binary(location_id) do
result = Geospatial.Service.service().get_by_id(location_id)

View file

@ -0,0 +1,28 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.Plugs.SetApplicationPlug do
import Plug.Conn, only: [assign: 3]
alias Pleroma.Repo
alias Pleroma.User
alias Pleroma.Web.OAuth.Token
def init(_), do: nil
def call(conn, _) do
assign(conn, :application, get_application(conn))
end
defp get_application(%{assigns: %{token: %Token{user: %User{} = user} = token}} = _conn) do
if user.disclose_client do
%{client_name: client_name, website: website} = Repo.preload(token, :app).app
%{type: "Application", name: client_name, url: website}
else
nil
end
end
defp get_application(_), do: nil
end

View file

@ -488,6 +488,7 @@ defmodule Pleroma.Web.Router do
post("/backups", BackupController, :create)
post("/events", EventController, :create)
put("/events/:id", EventController, :update)
get("/events/:id/participations", EventController, :participations)
get("/events/:id/participation_requests", EventController, :participation_requests)