Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F85824063
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Authored By
Unknown
Size
22 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/lib/pleroma/web/api_spec/operations/filter_operation.ex b/lib/pleroma/web/api_spec/operations/filter_operation.ex
index 0d673f566..53e57b46b 100644
--- a/lib/pleroma/web/api_spec/operations/filter_operation.ex
+++ b/lib/pleroma/web/api_spec/operations/filter_operation.ex
@@ -1,89 +1,227 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ApiSpec.FilterOperation do
alias OpenApiSpex.Operation
alias OpenApiSpex.Schema
alias Pleroma.Web.ApiSpec.Helpers
- alias Pleroma.Web.ApiSpec.Schemas.Filter
- alias Pleroma.Web.ApiSpec.Schemas.FilterCreateRequest
- alias Pleroma.Web.ApiSpec.Schemas.FiltersResponse
- alias Pleroma.Web.ApiSpec.Schemas.FilterUpdateRequest
def open_api_operation(action) do
operation = String.to_existing_atom("#{action}_operation")
apply(__MODULE__, operation, [])
end
def index_operation do
%Operation{
tags: ["apps"],
summary: "View all filters",
operationId: "FilterController.index",
security: [%{"oAuth" => ["read:filters"]}],
responses: %{
- 200 => Operation.response("Filters", "application/json", FiltersResponse)
+ 200 => Operation.response("Filters", "application/json", array_of_filters())
}
}
end
def create_operation do
%Operation{
tags: ["apps"],
summary: "Create a filter",
operationId: "FilterController.create",
- requestBody: Helpers.request_body("Parameters", FilterCreateRequest, required: true),
+ requestBody: Helpers.request_body("Parameters", create_request(), required: true),
security: [%{"oAuth" => ["write:filters"]}],
- responses: %{200 => Operation.response("Filter", "application/json", Filter)}
+ responses: %{200 => Operation.response("Filter", "application/json", filter())}
}
end
def show_operation do
%Operation{
tags: ["apps"],
summary: "View all filters",
parameters: [id_param()],
operationId: "FilterController.show",
security: [%{"oAuth" => ["read:filters"]}],
responses: %{
- 200 => Operation.response("Filter", "application/json", Filter)
+ 200 => Operation.response("Filter", "application/json", filter())
}
}
end
def update_operation do
%Operation{
tags: ["apps"],
summary: "Update a filter",
parameters: [id_param()],
operationId: "FilterController.update",
- requestBody: Helpers.request_body("Parameters", FilterUpdateRequest, required: true),
+ requestBody: Helpers.request_body("Parameters", update_request(), required: true),
security: [%{"oAuth" => ["write:filters"]}],
responses: %{
- 200 => Operation.response("Filter", "application/json", Filter)
+ 200 => Operation.response("Filter", "application/json", filter())
}
}
end
def delete_operation do
%Operation{
tags: ["apps"],
summary: "Remove a filter",
parameters: [id_param()],
operationId: "FilterController.delete",
security: [%{"oAuth" => ["write:filters"]}],
responses: %{
200 =>
Operation.response("Filter", "application/json", %Schema{
type: :object,
description: "Empty object"
})
}
}
end
defp id_param do
Operation.parameter(:id, :path, :string, "Filter ID", example: "123", required: true)
end
+
+ defp filter do
+ %Schema{
+ title: "Filter",
+ type: :object,
+ properties: %{
+ id: %Schema{type: :string},
+ phrase: %Schema{type: :string, description: "The text to be filtered"},
+ context: %Schema{
+ type: :array,
+ items: %Schema{type: :string, enum: ["home", "notifications", "public", "thread"]},
+ description: "The contexts in which the filter should be applied."
+ },
+ expires_at: %Schema{
+ type: :string,
+ format: :"date-time",
+ description:
+ "When the filter should no longer be applied. String (ISO 8601 Datetime), or null if the filter does not expire.",
+ nullable: true
+ },
+ irreversible: %Schema{
+ type: :boolean,
+ description:
+ "Should matching entities in home and notifications be dropped by the server?"
+ },
+ whole_word: %Schema{
+ type: :boolean,
+ description: "Should the filter consider word boundaries?"
+ }
+ },
+ example: %{
+ "id" => "5580",
+ "phrase" => "@twitter.com",
+ "context" => [
+ "home",
+ "notifications",
+ "public",
+ "thread"
+ ],
+ "whole_word" => false,
+ "expires_at" => nil,
+ "irreversible" => true
+ }
+ }
+ end
+
+ defp array_of_filters do
+ %Schema{
+ title: "ArrayOfFilters",
+ description: "Array of Filters",
+ type: :array,
+ items: filter(),
+ example: [
+ %{
+ "id" => "5580",
+ "phrase" => "@twitter.com",
+ "context" => [
+ "home",
+ "notifications",
+ "public",
+ "thread"
+ ],
+ "whole_word" => false,
+ "expires_at" => nil,
+ "irreversible" => true
+ },
+ %{
+ "id" => "6191",
+ "phrase" => ":eurovision2019:",
+ "context" => [
+ "home"
+ ],
+ "whole_word" => true,
+ "expires_at" => "2019-05-21T13:47:31.333Z",
+ "irreversible" => false
+ }
+ ]
+ }
+ end
+
+ defp create_request do
+ %Schema{
+ title: "FilterCreateRequest",
+ allOf: [
+ update_request(),
+ %Schema{
+ type: :object,
+ properties: %{
+ irreversible: %Schema{
+ type: :bolean,
+ description:
+ "Should the server irreversibly drop matching entities from home and notifications?",
+ default: false
+ }
+ }
+ }
+ ],
+ example: %{
+ "phrase" => "knights",
+ "context" => ["home"]
+ }
+ }
+ end
+
+ defp update_request do
+ %Schema{
+ title: "FilterUpdateRequest",
+ type: :object,
+ properties: %{
+ phrase: %Schema{type: :string, description: "The text to be filtered"},
+ context: %Schema{
+ type: :array,
+ items: %Schema{type: :string, enum: ["home", "notifications", "public", "thread"]},
+ description:
+ "Array of enumerable strings `home`, `notifications`, `public`, `thread`. At least one context must be specified."
+ },
+ irreversible: %Schema{
+ type: :bolean,
+ description:
+ "Should the server irreversibly drop matching entities from home and notifications?"
+ },
+ whole_word: %Schema{
+ type: :bolean,
+ description: "Consider word boundaries?",
+ default: true
+ }
+ # TODO: probably should implement filter expiration
+ # expires_in: %Schema{
+ # type: :string,
+ # format: :"date-time",
+ # description:
+ # "ISO 8601 Datetime for when the filter expires. Otherwise,
+ # null for a filter that doesn't expire."
+ # }
+ },
+ required: [:phrase, :context],
+ example: %{
+ "phrase" => "knights",
+ "context" => ["home"]
+ }
+ }
+ end
end
diff --git a/lib/pleroma/web/api_spec/schemas/filter.ex b/lib/pleroma/web/api_spec/schemas/filter.ex
deleted file mode 100644
index fc5480b71..000000000
--- a/lib/pleroma/web/api_spec/schemas/filter.ex
+++ /dev/null
@@ -1,51 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Web.ApiSpec.Schemas.Filter do
- alias OpenApiSpex.Schema
- require OpenApiSpex
-
- OpenApiSpex.schema(%{
- title: "Filter",
- type: :object,
- properties: %{
- id: %Schema{type: :string},
- phrase: %Schema{type: :string, description: "The text to be filtered"},
- context: %Schema{
- type: :array,
- items: %Schema{type: :string, enum: ["home", "notifications", "public", "thread"]},
- description: "The contexts in which the filter should be applied."
- },
- expires_at: %Schema{
- type: :string,
- format: :"date-time",
- description:
- "When the filter should no longer be applied. String (ISO 8601 Datetime), or null if the filter does not expire.",
- nullable: true
- },
- irreversible: %Schema{
- type: :boolean,
- description:
- "Should matching entities in home and notifications be dropped by the server?"
- },
- whole_word: %Schema{
- type: :boolean,
- description: "Should the filter consider word boundaries?"
- }
- },
- example: %{
- "id" => "5580",
- "phrase" => "@twitter.com",
- "context" => [
- "home",
- "notifications",
- "public",
- "thread"
- ],
- "whole_word" => false,
- "expires_at" => nil,
- "irreversible" => true
- }
- })
-end
diff --git a/lib/pleroma/web/api_spec/schemas/filter_create_request.ex b/lib/pleroma/web/api_spec/schemas/filter_create_request.ex
deleted file mode 100644
index f2a475b12..000000000
--- a/lib/pleroma/web/api_spec/schemas/filter_create_request.ex
+++ /dev/null
@@ -1,30 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Web.ApiSpec.Schemas.FilterCreateRequest do
- alias OpenApiSpex.Schema
- require OpenApiSpex
-
- OpenApiSpex.schema(%{
- title: "FilterCreateRequest",
- allOf: [
- %OpenApiSpex.Reference{"$ref": "#/components/schemas/FilterUpdateRequest"},
- %Schema{
- type: :object,
- properties: %{
- irreversible: %Schema{
- type: :bolean,
- description:
- "Should the server irreversibly drop matching entities from home and notifications?",
- default: false
- }
- }
- }
- ],
- example: %{
- "phrase" => "knights",
- "context" => ["home"]
- }
- })
-end
diff --git a/lib/pleroma/web/api_spec/schemas/filter_update_request.ex b/lib/pleroma/web/api_spec/schemas/filter_update_request.ex
deleted file mode 100644
index e703db0ce..000000000
--- a/lib/pleroma/web/api_spec/schemas/filter_update_request.ex
+++ /dev/null
@@ -1,41 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Web.ApiSpec.Schemas.FilterUpdateRequest do
- alias OpenApiSpex.Schema
- require OpenApiSpex
-
- OpenApiSpex.schema(%{
- title: "FilterUpdateRequest",
- type: :object,
- properties: %{
- phrase: %Schema{type: :string, description: "The text to be filtered"},
- context: %Schema{
- type: :array,
- items: %Schema{type: :string, enum: ["home", "notifications", "public", "thread"]},
- description:
- "Array of enumerable strings `home`, `notifications`, `public`, `thread`. At least one context must be specified."
- },
- irreversible: %Schema{
- type: :bolean,
- description:
- "Should the server irreversibly drop matching entities from home and notifications?"
- },
- whole_word: %Schema{type: :bolean, description: "Consider word boundaries?", default: true}
- # TODO: probably should implement filter expiration
- # expires_in: %Schema{
- # type: :string,
- # format: :"date-time",
- # description:
- # "ISO 8601 Datetime for when the filter expires. Otherwise,
- # null for a filter that doesn't expire."
- # }
- },
- required: [:phrase, :context],
- example: %{
- "phrase" => "knights",
- "context" => ["home"]
- }
- })
-end
diff --git a/lib/pleroma/web/api_spec/schemas/filters_response.ex b/lib/pleroma/web/api_spec/schemas/filters_response.ex
deleted file mode 100644
index 8c56c5982..000000000
--- a/lib/pleroma/web/api_spec/schemas/filters_response.ex
+++ /dev/null
@@ -1,40 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Web.ApiSpec.Schemas.FiltersResponse do
- require OpenApiSpex
- alias Pleroma.Web.ApiSpec.Schemas.Filter
-
- OpenApiSpex.schema(%{
- title: "FiltersResponse",
- description: "Array of Filters",
- type: :array,
- items: Filter,
- example: [
- %{
- "id" => "5580",
- "phrase" => "@twitter.com",
- "context" => [
- "home",
- "notifications",
- "public",
- "thread"
- ],
- "whole_word" => false,
- "expires_at" => nil,
- "irreversible" => true
- },
- %{
- "id" => "6191",
- "phrase" => ":eurovision2019:",
- "context" => [
- "home"
- ],
- "whole_word" => true,
- "expires_at" => "2019-05-21T13:47:31.333Z",
- "irreversible" => false
- }
- ]
- })
-end
diff --git a/lib/pleroma/web/mastodon_api/controllers/filter_controller.ex b/lib/pleroma/web/mastodon_api/controllers/filter_controller.ex
index dd13a8a09..21dc374cd 100644
--- a/lib/pleroma/web/mastodon_api/controllers/filter_controller.ex
+++ b/lib/pleroma/web/mastodon_api/controllers/filter_controller.ex
@@ -1,84 +1,83 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.MastodonAPI.FilterController do
use Pleroma.Web, :controller
alias Pleroma.Filter
alias Pleroma.Plugs.OAuthScopesPlug
@oauth_read_actions [:show, :index]
plug(Pleroma.Web.ApiSpec.CastAndValidate)
plug(OAuthScopesPlug, %{scopes: ["read:filters"]} when action in @oauth_read_actions)
plug(
OAuthScopesPlug,
%{scopes: ["write:filters"]} when action not in @oauth_read_actions
)
defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.FilterOperation
@doc "GET /api/v1/filters"
def index(%{assigns: %{user: user}} = conn, _) do
filters = Filter.get_filters(user)
render(conn, "index.json", filters: filters)
end
@doc "POST /api/v1/filters"
def create(%{assigns: %{user: user}, body_params: params} = conn, _) do
query = %Filter{
user_id: user.id,
phrase: params.phrase,
context: params.context,
hide: params.irreversible,
whole_word: params.whole_word
- # expires_at
+ # TODO: support `expires_in` parameter (as in Mastodon API)
}
{:ok, response} = Filter.create(query)
render(conn, "show.json", filter: response)
end
@doc "GET /api/v1/filters/:id"
def show(%{assigns: %{user: user}} = conn, %{id: filter_id}) do
filter = Filter.get(filter_id, user)
render(conn, "show.json", filter: filter)
end
@doc "PUT /api/v1/filters/:id"
def update(
%{assigns: %{user: user}, body_params: params} = conn,
%{id: filter_id}
) do
params =
params
- |> Map.from_struct()
|> Map.delete(:irreversible)
- |> Map.put(:hide, params.irreversible)
+ |> Map.put(:hide, params[:irreversible])
|> Enum.reject(fn {_key, value} -> is_nil(value) end)
|> Map.new()
- # TODO: add expires_in -> expires_at
+ # TODO: support `expires_in` parameter (as in Mastodon API)
with %Filter{} = filter <- Filter.get(filter_id, user),
{:ok, %Filter{} = filter} <- Filter.update(filter, params) do
render(conn, "show.json", filter: filter)
end
end
@doc "DELETE /api/v1/filters/:id"
def delete(%{assigns: %{user: user}} = conn, %{id: filter_id}) do
query = %Filter{
user_id: user.id,
filter_id: filter_id
}
{:ok, _} = Filter.delete(query)
json(conn, %{})
end
end
diff --git a/lib/pleroma/web/mastodon_api/views/filter_view.ex b/lib/pleroma/web/mastodon_api/views/filter_view.ex
index 8d5c381ec..aeff646f5 100644
--- a/lib/pleroma/web/mastodon_api/views/filter_view.ex
+++ b/lib/pleroma/web/mastodon_api/views/filter_view.ex
@@ -1,31 +1,31 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.MastodonAPI.FilterView do
use Pleroma.Web, :view
alias Pleroma.Web.CommonAPI.Utils
alias Pleroma.Web.MastodonAPI.FilterView
- def render("index.json", %{filters: filters} = opts) do
- render_many(filters, FilterView, "show.json", opts)
+ def render("index.json", %{filters: filters}) do
+ render_many(filters, FilterView, "show.json")
end
def render("show.json", %{filter: filter}) do
expires_at =
if filter.expires_at do
Utils.to_masto_date(filter.expires_at)
else
nil
end
%{
id: to_string(filter.filter_id),
phrase: filter.phrase,
context: filter.context,
expires_at: expires_at,
irreversible: filter.hide,
whole_word: false
}
end
end
diff --git a/test/web/mastodon_api/controllers/filter_controller_test.exs b/test/web/mastodon_api/controllers/filter_controller_test.exs
index 41a290eb2..f29547d13 100644
--- a/test/web/mastodon_api/controllers/filter_controller_test.exs
+++ b/test/web/mastodon_api/controllers/filter_controller_test.exs
@@ -1,168 +1,129 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.MastodonAPI.FilterControllerTest do
use Pleroma.Web.ConnCase
- alias Pleroma.Web.ApiSpec
- alias Pleroma.Web.ApiSpec.Schemas.Filter
- alias Pleroma.Web.ApiSpec.Schemas.FilterCreateRequest
- alias Pleroma.Web.ApiSpec.Schemas.FiltersResponse
- alias Pleroma.Web.ApiSpec.Schemas.FilterUpdateRequest
alias Pleroma.Web.MastodonAPI.FilterView
- import OpenApiSpex.TestAssertions
-
test "creating a filter" do
%{conn: conn} = oauth_access(["write:filters"])
filter = %Pleroma.Filter{
phrase: "knights",
context: ["home"]
}
conn =
conn
|> put_req_header("content-type", "application/json")
|> post("/api/v1/filters", %{"phrase" => filter.phrase, context: filter.context})
- assert response = json_response(conn, 200)
+ assert response = json_response_and_validate_schema(conn, 200)
assert response["phrase"] == filter.phrase
assert response["context"] == filter.context
assert response["irreversible"] == false
assert response["id"] != nil
assert response["id"] != ""
- assert_schema(response, "Filter", ApiSpec.spec())
end
test "fetching a list of filters" do
%{user: user, conn: conn} = oauth_access(["read:filters"])
query_one = %Pleroma.Filter{
user_id: user.id,
filter_id: 1,
phrase: "knights",
context: ["home"]
}
query_two = %Pleroma.Filter{
user_id: user.id,
filter_id: 2,
phrase: "who",
context: ["home"]
}
{:ok, filter_one} = Pleroma.Filter.create(query_one)
{:ok, filter_two} = Pleroma.Filter.create(query_two)
response =
conn
|> get("/api/v1/filters")
- |> json_response(200)
+ |> json_response_and_validate_schema(200)
assert response ==
render_json(
FilterView,
"index.json",
filters: [filter_two, filter_one]
)
-
- assert_schema(response, "FiltersResponse", ApiSpec.spec())
end
test "get a filter" do
%{user: user, conn: conn} = oauth_access(["read:filters"])
query = %Pleroma.Filter{
user_id: user.id,
filter_id: 2,
phrase: "knight",
context: ["home"]
}
{:ok, filter} = Pleroma.Filter.create(query)
conn = get(conn, "/api/v1/filters/#{filter.filter_id}")
- assert response = json_response(conn, 200)
- assert_schema(response, "Filter", ApiSpec.spec())
+ assert response = json_response_and_validate_schema(conn, 200)
end
test "update a filter" do
%{user: user, conn: conn} = oauth_access(["write:filters"])
query = %Pleroma.Filter{
user_id: user.id,
filter_id: 2,
phrase: "knight",
context: ["home"],
hide: true
}
{:ok, _filter} = Pleroma.Filter.create(query)
new = %Pleroma.Filter{
phrase: "nii",
context: ["home"]
}
conn =
conn
|> put_req_header("content-type", "application/json")
|> put("/api/v1/filters/#{query.filter_id}", %{
phrase: new.phrase,
context: new.context
})
- assert response = json_response(conn, 200)
+ assert response = json_response_and_validate_schema(conn, 200)
assert response["phrase"] == new.phrase
assert response["context"] == new.context
assert response["irreversible"] == true
- assert_schema(response, "Filter", ApiSpec.spec())
end
test "delete a filter" do
%{user: user, conn: conn} = oauth_access(["write:filters"])
query = %Pleroma.Filter{
user_id: user.id,
filter_id: 2,
phrase: "knight",
context: ["home"]
}
{:ok, filter} = Pleroma.Filter.create(query)
conn = delete(conn, "/api/v1/filters/#{filter.filter_id}")
- assert response = json_response(conn, 200)
- assert response == %{}
- end
-
- describe "OpenAPI" do
- test "Filter example matches schema" do
- api_spec = ApiSpec.spec()
- schema = Filter.schema()
- assert_schema(schema.example, "Filter", api_spec)
- end
-
- test "FiltersResponse example matches schema" do
- api_spec = ApiSpec.spec()
- schema = FiltersResponse.schema()
- assert_schema(schema.example, "FiltersResponse", api_spec)
- end
-
- test "FilterCreateRequest example matches schema" do
- api_spec = ApiSpec.spec()
- schema = FilterCreateRequest.schema()
- assert_schema(schema.example, "FilterCreateRequest", api_spec)
- end
-
- test "FilterUpdateRequest example matches schema" do
- api_spec = ApiSpec.spec()
- schema = FilterUpdateRequest.schema()
- assert_schema(schema.example, "FilterUpdateRequest", api_spec)
- end
+ assert json_response_and_validate_schema(conn, 200) == %{}
end
end
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Thu, Oct 29, 11:11 AM (21 h, 50 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1798028
Default Alt Text
(22 KB)
Attached To
Mode
rPUBE pleroma-upstream
Attached
Detach File
Event Timeline