alias Pleroma.Web.CommonAPI
alias Pleroma.Web.Endpoint
alias Pleroma.Web.MastodonAPI
- alias Pleroma.Web.MastodonAPI.AppView
- alias Pleroma.Web.OAuth.App
alias Pleroma.Web.Router
require Logger
:config_update,
:resend_confirmation_email,
:confirm_email,
- :oauth_app_create,
- :oauth_app_list,
- :oauth_app_update,
- :oauth_app_delete,
:reload_emoji
]
)
conn |> json("")
end
- def oauth_app_create(conn, params) do
- params =
- if params["name"] do
- Map.put(params, "client_name", params["name"])
- else
- params
- end
-
- result =
- case App.create(params) do
- {:ok, app} ->
- AppView.render("show.json", %{app: app, admin: true})
-
- {:error, changeset} ->
- App.errors(changeset)
- end
-
- json(conn, result)
- end
-
- def oauth_app_update(conn, params) do
- params =
- if params["name"] do
- Map.put(params, "client_name", params["name"])
- else
- params
- end
-
- with {:ok, app} <- App.update(params) do
- json(conn, AppView.render("show.json", %{app: app, admin: true}))
- else
- {:error, changeset} ->
- json(conn, App.errors(changeset))
-
- nil ->
- json_response(conn, :bad_request, "")
- end
- end
-
- def oauth_app_list(conn, params) do
- {page, page_size} = page_params(params)
-
- search_params = %{
- client_name: params["name"],
- client_id: params["client_id"],
- page: page,
- page_size: page_size
- }
-
- search_params =
- if Map.has_key?(params, "trusted") do
- Map.put(search_params, :trusted, params["trusted"])
- else
- search_params
- end
-
- with {:ok, apps, count} <- App.search(search_params) do
- json(
- conn,
- AppView.render("index.json",
- apps: apps,
- count: count,
- page_size: page_size,
- admin: true
- )
- )
- end
- end
-
- def oauth_app_delete(conn, params) do
- with {:ok, _app} <- App.destroy(params["id"]) do
- json_response(conn, :no_content, "")
- else
- _ -> json_response(conn, :bad_request, "")
- end
- end
-
def stats(conn, _) do
count = Stats.get_status_visibility_count()
--- /dev/null
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.AdminAPI.OAuthAppController do
+ use Pleroma.Web, :controller
+
+ import Pleroma.Web.ControllerHelper, only: [json_response: 3]
+
+ alias Pleroma.Plugs.OAuthScopesPlug
+ alias Pleroma.Web.OAuth.App
+
+ require Logger
+
+ plug(Pleroma.Web.ApiSpec.CastAndValidate)
+ plug(:put_view, Pleroma.Web.MastodonAPI.AppView)
+
+ plug(
+ OAuthScopesPlug,
+ %{scopes: ["write"], admin: true}
+ when action in [:create, :index, :update, :delete]
+ )
+
+ action_fallback(Pleroma.Web.AdminAPI.FallbackController)
+
+ defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.Admin.OAuthAppOperation
+
+ def index(conn, params) do
+ search_params =
+ params
+ |> Map.take([:client_id, :page, :page_size, :trusted])
+ |> Map.put(:client_name, params[:name])
+
+ with {:ok, apps, count} <- App.search(search_params) do
+ render(conn, "index.json",
+ apps: apps,
+ count: count,
+ page_size: params.page_size,
+ admin: true
+ )
+ end
+ end
+
+ def create(%{body_params: params} = conn, _) do
+ params =
+ if params[:name] do
+ Map.put(params, :client_name, params[:name])
+ else
+ params
+ end
+
+ case App.create(params) do
+ {:ok, app} ->
+ render(conn, "show.json", app: app, admin: true)
+
+ {:error, changeset} ->
+ json(conn, App.errors(changeset))
+ end
+ end
+
+ def update(%{body_params: params} = conn, %{id: id}) do
+ params =
+ if params[:name] do
+ Map.put(params, :client_name, params.name)
+ else
+ params
+ end
+
+ with {:ok, app} <- App.update(id, params) do
+ render(conn, "show.json", app: app, admin: true)
+ else
+ {:error, changeset} ->
+ json(conn, App.errors(changeset))
+
+ nil ->
+ json_response(conn, :bad_request, "")
+ end
+ end
+
+ def delete(conn, params) do
+ with {:ok, _app} <- App.destroy(params.id) do
+ json_response(conn, :no_content, "")
+ else
+ _ -> json_response(conn, :bad_request, "")
+ end
+ end
+end
--- /dev/null
+# 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.Admin.OAuthAppOperation do
+ alias OpenApiSpex.Operation
+ alias OpenApiSpex.Schema
+ alias Pleroma.Web.ApiSpec.Schemas.ApiError
+
+ import Pleroma.Web.ApiSpec.Helpers
+
+ def open_api_operation(action) do
+ operation = String.to_existing_atom("#{action}_operation")
+ apply(__MODULE__, operation, [])
+ end
+
+ def index_operation do
+ %Operation{
+ summary: "List OAuth apps",
+ tags: ["Admin", "oAuth Apps"],
+ operationId: "AdminAPI.OAuthAppController.index",
+ security: [%{"oAuth" => ["write"]}],
+ parameters: [
+ Operation.parameter(:name, :query, %Schema{type: :string}, "App name"),
+ Operation.parameter(:client_id, :query, %Schema{type: :string}, "Client ID"),
+ Operation.parameter(:page, :query, %Schema{type: :integer, default: 1}, "Page"),
+ Operation.parameter(
+ :trusted,
+ :query,
+ %Schema{type: :boolean, default: false},
+ "Trusted apps"
+ ),
+ Operation.parameter(
+ :page_size,
+ :query,
+ %Schema{type: :integer, default: 50},
+ "Number of apps to return"
+ )
+ ],
+ responses: %{
+ 200 =>
+ Operation.response("List of apps", "application/json", %Schema{
+ type: :object,
+ properties: %{
+ apps: %Schema{type: :array, items: oauth_app()},
+ count: %Schema{type: :integer},
+ page_size: %Schema{type: :integer}
+ },
+ example: %{
+ "apps" => [
+ %{
+ "id" => 1,
+ "name" => "App name",
+ "client_id" => "yHoDSiWYp5mPV6AfsaVOWjdOyt5PhWRiafi6MRd1lSk",
+ "client_secret" => "nLmis486Vqrv2o65eM9mLQx_m_4gH-Q6PcDpGIMl6FY",
+ "redirect_uri" => "https://example.com/oauth-callback",
+ "website" => "https://example.com",
+ "trusted" => true
+ }
+ ],
+ "count" => 1,
+ "page_size" => 50
+ }
+ })
+ }
+ }
+ end
+
+ def create_operation do
+ %Operation{
+ tags: ["Admin", "oAuth Apps"],
+ summary: "Create OAuth App",
+ operationId: "AdminAPI.OAuthAppController.create",
+ requestBody: request_body("Parameters", create_request()),
+ security: [%{"oAuth" => ["write"]}],
+ responses: %{
+ 200 => Operation.response("App", "application/json", oauth_app()),
+ 400 => Operation.response("Bad Request", "application/json", ApiError)
+ }
+ }
+ end
+
+ def update_operation do
+ %Operation{
+ tags: ["Admin", "oAuth Apps"],
+ summary: "Update OAuth App",
+ operationId: "AdminAPI.OAuthAppController.update",
+ parameters: [id_param()],
+ security: [%{"oAuth" => ["write"]}],
+ requestBody: request_body("Parameters", update_request()),
+ responses: %{
+ 200 => Operation.response("App", "application/json", oauth_app()),
+ 400 =>
+ Operation.response("Bad Request", "application/json", %Schema{
+ oneOf: [ApiError, %Schema{type: :string}]
+ })
+ }
+ }
+ end
+
+ def delete_operation do
+ %Operation{
+ tags: ["Admin", "oAuth Apps"],
+ summary: "Delete OAuth App",
+ operationId: "AdminAPI.OAuthAppController.delete",
+ parameters: [id_param()],
+ security: [%{"oAuth" => ["write"]}],
+ responses: %{
+ 204 => no_content_response(),
+ 400 => no_content_response()
+ }
+ }
+ end
+
+ defp create_request do
+ %Schema{
+ title: "oAuthAppCreateRequest",
+ type: :object,
+ required: [:name, :redirect_uris],
+ properties: %{
+ name: %Schema{type: :string, description: "Application Name"},
+ scopes: %Schema{type: :array, items: %Schema{type: :string}, description: "oAuth scopes"},
+ redirect_uris: %Schema{
+ type: :string,
+ description:
+ "Where the user should be redirected after authorization. To display the authorization code to the user instead of redirecting to a web page, use `urn:ietf:wg:oauth:2.0:oob` in this parameter."
+ },
+ website: %Schema{
+ type: :string,
+ nullable: true,
+ description: "A URL to the homepage of the app"
+ },
+ trusted: %Schema{
+ type: :boolean,
+ nullable: true,
+ default: false,
+ description: "Is the app trusted?"
+ }
+ },
+ example: %{
+ "name" => "My App",
+ "redirect_uris" => "https://myapp.com/auth/callback",
+ "website" => "https://myapp.com/",
+ "scopes" => ["read", "write"],
+ "trusted" => true
+ }
+ }
+ end
+
+ defp update_request do
+ %Schema{
+ title: "oAuthAppUpdateRequest",
+ type: :object,
+ properties: %{
+ name: %Schema{type: :string, description: "Application Name"},
+ scopes: %Schema{type: :array, items: %Schema{type: :string}, description: "oAuth scopes"},
+ redirect_uris: %Schema{
+ type: :string,
+ description:
+ "Where the user should be redirected after authorization. To display the authorization code to the user instead of redirecting to a web page, use `urn:ietf:wg:oauth:2.0:oob` in this parameter."
+ },
+ website: %Schema{
+ type: :string,
+ nullable: true,
+ description: "A URL to the homepage of the app"
+ },
+ trusted: %Schema{
+ type: :boolean,
+ nullable: true,
+ default: false,
+ description: "Is the app trusted?"
+ }
+ },
+ example: %{
+ "name" => "My App",
+ "redirect_uris" => "https://myapp.com/auth/callback",
+ "website" => "https://myapp.com/",
+ "scopes" => ["read", "write"],
+ "trusted" => true
+ }
+ }
+ end
+
+ defp oauth_app do
+ %Schema{
+ title: "oAuthApp",
+ type: :object,
+ properties: %{
+ id: %Schema{type: :integer},
+ name: %Schema{type: :string},
+ client_id: %Schema{type: :string},
+ client_secret: %Schema{type: :string},
+ redirect_uri: %Schema{type: :string},
+ website: %Schema{type: :string, nullable: true},
+ trusted: %Schema{type: :boolean}
+ },
+ example: %{
+ "id" => 123,
+ "name" => "My App",
+ "client_id" => "TWhM-tNSuncnqN7DBJmoyeLnk6K3iJJ71KKXxgL1hPM",
+ "client_secret" => "ZEaFUFmF0umgBX1qKJDjaU99Q31lDkOU8NutzTOoliw",
+ "redirect_uri" => "https://myapp.com/oauth-callback",
+ "website" => "https://myapp.com/",
+ "trusted" => false
+ }
+ }
+ end
+
+ def id_param do
+ Operation.parameter(:id, :path, :integer, "App ID",
+ example: 1337,
+ required: true
+ )
+ end
+end
timestamps()
end
- @spec changeset(App.t(), map()) :: Ecto.Changeset.t()
+ @spec changeset(t(), map()) :: Ecto.Changeset.t()
def changeset(struct, params) do
cast(struct, params, [:client_name, :redirect_uris, :scopes, :website, :trusted])
end
- @spec register_changeset(App.t(), map()) :: Ecto.Changeset.t()
+ @spec register_changeset(t(), map()) :: Ecto.Changeset.t()
def register_changeset(struct, params \\ %{}) do
changeset =
struct
end
end
- @spec create(map()) :: {:ok, App.t()} | {:error, Ecto.Changeset.t()}
+ @spec create(map()) :: {:ok, t()} | {:error, Ecto.Changeset.t()}
def create(params) do
- with changeset <- __MODULE__.register_changeset(%__MODULE__{}, params) do
- Repo.insert(changeset)
- end
+ %__MODULE__{}
+ |> register_changeset(params)
+ |> Repo.insert()
end
- @spec update(map()) :: {:ok, App.t()} | {:error, Ecto.Changeset.t()}
- def update(params) do
- with %__MODULE__{} = app <- Repo.get(__MODULE__, params["id"]),
- changeset <- changeset(app, params) do
- Repo.update(changeset)
+ @spec update(pos_integer(), map()) :: {:ok, t()} | {:error, Ecto.Changeset.t()}
+ def update(id, params) do
+ with %__MODULE__{} = app <- Repo.get(__MODULE__, id) do
+ app
+ |> changeset(params)
+ |> Repo.update()
end
end
Gets app by attrs or create new with attrs.
And updates the scopes if need.
"""
- @spec get_or_make(map(), list(String.t())) :: {:ok, App.t()} | {:error, Ecto.Changeset.t()}
+ @spec get_or_make(map(), list(String.t())) :: {:ok, t()} | {:error, Ecto.Changeset.t()}
def get_or_make(attrs, scopes) do
with %__MODULE__{} = app <- Repo.get_by(__MODULE__, attrs) do
update_scopes(app, scopes)
|> Repo.update()
end
- @spec search(map()) :: {:ok, [App.t()], non_neg_integer()}
+ @spec search(map()) :: {:ok, [t()], non_neg_integer()}
def search(params) do
query = from(a in __MODULE__)
{:ok, Repo.all(query), count}
end
- @spec destroy(pos_integer()) :: {:ok, App.t()} | {:error, Ecto.Changeset.t()}
+ @spec destroy(pos_integer()) :: {:ok, t()} | {:error, Ecto.Changeset.t()}
def destroy(id) do
with %__MODULE__{} = app <- Repo.get(__MODULE__, id) do
Repo.delete(app)
post("/reload_emoji", AdminAPIController, :reload_emoji)
get("/stats", AdminAPIController, :stats)
- get("/oauth_app", AdminAPIController, :oauth_app_list)
- post("/oauth_app", AdminAPIController, :oauth_app_create)
- patch("/oauth_app/:id", AdminAPIController, :oauth_app_update)
- delete("/oauth_app/:id", AdminAPIController, :oauth_app_delete)
+ get("/oauth_app", OAuthAppController, :index)
+ post("/oauth_app", OAuthAppController, :create)
+ patch("/oauth_app/:id", OAuthAppController, :update)
+ delete("/oauth_app/:id", OAuthAppController, :delete)
end
scope "/api/pleroma/emoji", Pleroma.Web.PleromaAPI do
response["status_visibility"]
end
end
-
- describe "POST /api/pleroma/admin/oauth_app" do
- test "errors", %{conn: conn} do
- response = conn |> post("/api/pleroma/admin/oauth_app", %{}) |> json_response(200)
-
- assert response == %{"name" => "can't be blank", "redirect_uris" => "can't be blank"}
- end
-
- test "success", %{conn: conn} do
- base_url = Web.base_url()
- app_name = "Trusted app"
-
- response =
- conn
- |> post("/api/pleroma/admin/oauth_app", %{
- name: app_name,
- redirect_uris: base_url
- })
- |> json_response(200)
-
- assert %{
- "client_id" => _,
- "client_secret" => _,
- "name" => ^app_name,
- "redirect_uri" => ^base_url,
- "trusted" => false
- } = response
- end
-
- test "with trusted", %{conn: conn} do
- base_url = Web.base_url()
- app_name = "Trusted app"
-
- response =
- conn
- |> post("/api/pleroma/admin/oauth_app", %{
- name: app_name,
- redirect_uris: base_url,
- trusted: true
- })
- |> json_response(200)
-
- assert %{
- "client_id" => _,
- "client_secret" => _,
- "name" => ^app_name,
- "redirect_uri" => ^base_url,
- "trusted" => true
- } = response
- end
- end
-
- describe "GET /api/pleroma/admin/oauth_app" do
- setup do
- app = insert(:oauth_app)
- {:ok, app: app}
- end
-
- test "list", %{conn: conn} do
- response =
- conn
- |> get("/api/pleroma/admin/oauth_app")
- |> json_response(200)
-
- assert %{"apps" => apps, "count" => count, "page_size" => _} = response
-
- assert length(apps) == count
- end
-
- test "with page size", %{conn: conn} do
- insert(:oauth_app)
- page_size = 1
-
- response =
- conn
- |> get("/api/pleroma/admin/oauth_app", %{page_size: to_string(page_size)})
- |> json_response(200)
-
- assert %{"apps" => apps, "count" => _, "page_size" => ^page_size} = response
-
- assert length(apps) == page_size
- end
-
- test "search by client name", %{conn: conn, app: app} do
- response =
- conn
- |> get("/api/pleroma/admin/oauth_app", %{name: app.client_name})
- |> json_response(200)
-
- assert %{"apps" => [returned], "count" => _, "page_size" => _} = response
-
- assert returned["client_id"] == app.client_id
- assert returned["name"] == app.client_name
- end
-
- test "search by client id", %{conn: conn, app: app} do
- response =
- conn
- |> get("/api/pleroma/admin/oauth_app", %{client_id: app.client_id})
- |> json_response(200)
-
- assert %{"apps" => [returned], "count" => _, "page_size" => _} = response
-
- assert returned["client_id"] == app.client_id
- assert returned["name"] == app.client_name
- end
-
- test "only trusted", %{conn: conn} do
- app = insert(:oauth_app, trusted: true)
-
- response =
- conn
- |> get("/api/pleroma/admin/oauth_app", %{trusted: true})
- |> json_response(200)
-
- assert %{"apps" => [returned], "count" => _, "page_size" => _} = response
-
- assert returned["client_id"] == app.client_id
- assert returned["name"] == app.client_name
- end
- end
-
- describe "DELETE /api/pleroma/admin/oauth_app/:id" do
- test "with id", %{conn: conn} do
- app = insert(:oauth_app)
-
- response =
- conn
- |> delete("/api/pleroma/admin/oauth_app/" <> to_string(app.id))
- |> json_response(:no_content)
-
- assert response == ""
- end
-
- test "with non existance id", %{conn: conn} do
- response =
- conn
- |> delete("/api/pleroma/admin/oauth_app/0")
- |> json_response(:bad_request)
-
- assert response == ""
- end
- end
-
- describe "PATCH /api/pleroma/admin/oauth_app/:id" do
- test "with id", %{conn: conn} do
- app = insert(:oauth_app)
-
- name = "another name"
- url = "https://example.com"
- scopes = ["admin"]
- id = app.id
- website = "http://website.com"
-
- response =
- conn
- |> patch("/api/pleroma/admin/oauth_app/" <> to_string(app.id), %{
- name: name,
- trusted: true,
- redirect_uris: url,
- scopes: scopes,
- website: website
- })
- |> json_response(200)
-
- assert %{
- "client_id" => _,
- "client_secret" => _,
- "id" => ^id,
- "name" => ^name,
- "redirect_uri" => ^url,
- "trusted" => true,
- "website" => ^website
- } = response
- end
-
- test "without id", %{conn: conn} do
- response =
- conn
- |> patch("/api/pleroma/admin/oauth_app/0")
- |> json_response(:bad_request)
-
- assert response == ""
- end
- end
end
# Needed for testing
--- /dev/null
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.AdminAPI.OAuthAppControllerTest do
+ use Pleroma.Web.ConnCase, async: true
+ use Oban.Testing, repo: Pleroma.Repo
+
+ import Pleroma.Factory
+
+ alias Pleroma.Config
+ alias Pleroma.Web
+
+ setup do
+ admin = insert(:user, is_admin: true)
+ token = insert(:oauth_admin_token, user: admin)
+
+ conn =
+ build_conn()
+ |> assign(:user, admin)
+ |> assign(:token, token)
+
+ {:ok, %{admin: admin, token: token, conn: conn}}
+ end
+
+ describe "POST /api/pleroma/admin/oauth_app" do
+ test "errors", %{conn: conn} do
+ response =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/pleroma/admin/oauth_app", %{})
+ |> json_response_and_validate_schema(400)
+
+ assert %{
+ "error" => "Missing field: name. Missing field: redirect_uris."
+ } = response
+ end
+
+ test "success", %{conn: conn} do
+ base_url = Web.base_url()
+ app_name = "Trusted app"
+
+ response =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/pleroma/admin/oauth_app", %{
+ name: app_name,
+ redirect_uris: base_url
+ })
+ |> json_response_and_validate_schema(200)
+
+ assert %{
+ "client_id" => _,
+ "client_secret" => _,
+ "name" => ^app_name,
+ "redirect_uri" => ^base_url,
+ "trusted" => false
+ } = response
+ end
+
+ test "with trusted", %{conn: conn} do
+ base_url = Web.base_url()
+ app_name = "Trusted app"
+
+ response =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/pleroma/admin/oauth_app", %{
+ name: app_name,
+ redirect_uris: base_url,
+ trusted: true
+ })
+ |> json_response_and_validate_schema(200)
+
+ assert %{
+ "client_id" => _,
+ "client_secret" => _,
+ "name" => ^app_name,
+ "redirect_uri" => ^base_url,
+ "trusted" => true
+ } = response
+ end
+ end
+
+ describe "GET /api/pleroma/admin/oauth_app" do
+ setup do
+ app = insert(:oauth_app)
+ {:ok, app: app}
+ end
+
+ test "list", %{conn: conn} do
+ response =
+ conn
+ |> get("/api/pleroma/admin/oauth_app")
+ |> json_response_and_validate_schema(200)
+
+ assert %{"apps" => apps, "count" => count, "page_size" => _} = response
+
+ assert length(apps) == count
+ end
+
+ test "with page size", %{conn: conn} do
+ insert(:oauth_app)
+ page_size = 1
+
+ response =
+ conn
+ |> get("/api/pleroma/admin/oauth_app?page_size=#{page_size}")
+ |> json_response_and_validate_schema(200)
+
+ assert %{"apps" => apps, "count" => _, "page_size" => ^page_size} = response
+
+ assert length(apps) == page_size
+ end
+
+ test "search by client name", %{conn: conn, app: app} do
+ response =
+ conn
+ |> get("/api/pleroma/admin/oauth_app?name=#{app.client_name}")
+ |> json_response_and_validate_schema(200)
+
+ assert %{"apps" => [returned], "count" => _, "page_size" => _} = response
+
+ assert returned["client_id"] == app.client_id
+ assert returned["name"] == app.client_name
+ end
+
+ test "search by client id", %{conn: conn, app: app} do
+ response =
+ conn
+ |> get("/api/pleroma/admin/oauth_app?client_id=#{app.client_id}")
+ |> json_response_and_validate_schema(200)
+
+ assert %{"apps" => [returned], "count" => _, "page_size" => _} = response
+
+ assert returned["client_id"] == app.client_id
+ assert returned["name"] == app.client_name
+ end
+
+ test "only trusted", %{conn: conn} do
+ app = insert(:oauth_app, trusted: true)
+
+ response =
+ conn
+ |> get("/api/pleroma/admin/oauth_app?trusted=true")
+ |> json_response_and_validate_schema(200)
+
+ assert %{"apps" => [returned], "count" => _, "page_size" => _} = response
+
+ assert returned["client_id"] == app.client_id
+ assert returned["name"] == app.client_name
+ end
+ end
+
+ describe "DELETE /api/pleroma/admin/oauth_app/:id" do
+ test "with id", %{conn: conn} do
+ app = insert(:oauth_app)
+
+ response =
+ conn
+ |> delete("/api/pleroma/admin/oauth_app/" <> to_string(app.id))
+ |> json_response_and_validate_schema(:no_content)
+
+ assert response == ""
+ end
+
+ test "with non existance id", %{conn: conn} do
+ response =
+ conn
+ |> delete("/api/pleroma/admin/oauth_app/0")
+ |> json_response_and_validate_schema(:bad_request)
+
+ assert response == ""
+ end
+ end
+
+ describe "PATCH /api/pleroma/admin/oauth_app/:id" do
+ test "with id", %{conn: conn} do
+ app = insert(:oauth_app)
+
+ name = "another name"
+ url = "https://example.com"
+ scopes = ["admin"]
+ id = app.id
+ website = "http://website.com"
+
+ response =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> patch("/api/pleroma/admin/oauth_app/#{id}", %{
+ name: name,
+ trusted: true,
+ redirect_uris: url,
+ scopes: scopes,
+ website: website
+ })
+ |> json_response_and_validate_schema(200)
+
+ assert %{
+ "client_id" => _,
+ "client_secret" => _,
+ "id" => ^id,
+ "name" => ^name,
+ "redirect_uri" => ^url,
+ "trusted" => true,
+ "website" => ^website
+ } = response
+ end
+
+ test "without id", %{conn: conn} do
+ response =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> patch("/api/pleroma/admin/oauth_app/0")
+ |> json_response_and_validate_schema(:bad_request)
+
+ assert response == ""
+ end
+ end
+end