From b5f59d5be0e4d0c26a6103f47b05adda555ce231 Mon Sep 17 00:00:00 2001
From: Michael <heluecht@pirati.ca>
Date: Tue, 20 Jul 2021 20:48:37 +0000
Subject: [PATCH] API: Support for deprecated API endpoints and OAuth removal

---
 CHANGELOG                                     |  1 +
 doc/API-GNU-Social.md                         |  4 +-
 doc/API-Mastodon.md                           |  2 +
 doc/Addons.md                                 |  4 --
 doc/api.md                                    |  4 +-
 include/api.php                               |  2 +-
 src/Module/Api/Mastodon/Search.php            | 12 ++--
 src/Module/Api/Mastodon/Statuses/Card.php     | 57 +++++++++++++++++++
 static/routes.config.php                      |  3 +-
 view/templates/oauth_authorize_done.tpl       |  5 --
 view/templates/settings/oauth_edit.tpl        | 18 ------
 .../frio/templates/settings/oauth_edit.tpl    | 19 -------
 12 files changed, 74 insertions(+), 57 deletions(-)
 create mode 100644 src/Module/Api/Mastodon/Statuses/Card.php
 delete mode 100644 view/templates/oauth_authorize_done.tpl
 delete mode 100644 view/templates/settings/oauth_edit.tpl
 delete mode 100644 view/theme/frio/templates/settings/oauth_edit.tpl

diff --git a/CHANGELOG b/CHANGELOG
index cbbbee76db..2c7e4fc43e 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -2,6 +2,7 @@ Version 2021.09 (unreleased)
   Friendica Core
     Simplified the proxy mechanism. The proxy cache directory (/proxy) can now be removed [annando]
     DFRN is now always handled with the Diaspora transport layer. The legacy DFRN transport layer is removed [annando]
+    Legacy OAuth server is removed [annando]
 
 Version 2021.07 (2021-07-04)
   Friendica Core
diff --git a/doc/API-GNU-Social.md b/doc/API-GNU-Social.md
index 157450666b..a33825fc80 100644
--- a/doc/API-GNU-Social.md
+++ b/doc/API-GNU-Social.md
@@ -30,8 +30,6 @@ These endpoints use the [Friendica API entities](help/API-Entities).
 - POST api/friendships/destroy
 - GET api/friends/ids
 - GET/POST api/help/test
-- POST api/oauth/access_token
-- POST api/oauth/request_token
 - GET api/search
 - GET api/statuses/show/:id
 - POST api/statuses/destroy/:id
@@ -67,6 +65,8 @@ These endpoints use the [Friendica API entities](help/API-Entities).
 - blocks/exists
 - blocks/blocking
 - oauth/authorize
+- oauth/access_token
+- oauth/request_token
 - statusnet/groups/timeline
 - statusnet/groups/show
 - statusnet/groups/create
diff --git a/doc/API-Mastodon.md b/doc/API-Mastodon.md
index 2c0f613a25..2eadc2a1bd 100644
--- a/doc/API-Mastodon.md
+++ b/doc/API-Mastodon.md
@@ -93,9 +93,11 @@ These endpoints use the [Mastodon API entities](https://docs.joinmastodon.org/en
 - [`POST /api/v1/notifications/clear`](https://docs.joinmastodon.org/methods/notifications/)
 - [`POST /api/v1/notifications/:id/dismiss`](https://docs.joinmastodon.org/methods/notifications/)
 - [`GET /api/v1/preferences`](https://docs.joinmastodon.org/methods/accounts/preferences/)
+- [`GET /api/v1/search`](https://docs.joinmastodon.org/methods/search/)
 - [`POST /api/v1/statuses`](https://docs.joinmastodon.org/methods/statuses/)
 - [`GET /api/v1/statuses/:id`](https://docs.joinmastodon.org/methods/statuses/)
 - [`DELETE /api/v1/statuses/:id`](https://docs.joinmastodon.org/methods/statuses/)
+- [`GET /api/v1/statuses/:id/card`](https://docs.joinmastodon.org/methods/statuses/)
 - [`GET /api/v1/statuses/:id/context`](https://docs.joinmastodon.org/methods/statuses/)
 - [`GET /api/v1/statuses/:id/reblogged_by`](https://docs.joinmastodon.org/methods/statuses/)
 - [`GET /api/v1/statuses/:id/favourited_by`](https://docs.joinmastodon.org/methods/statuses/)
diff --git a/doc/Addons.md b/doc/Addons.md
index a058753605..a1c2c03ce2 100644
--- a/doc/Addons.md
+++ b/doc/Addons.md
@@ -619,10 +619,6 @@ Here is a complete list of all hook callbacks with file locations (as of 24-Sep-
 
     Hook::callAll('jot_tool', $jotplugins);
 
-### src/Network/FKOAuth1.php
-
-    Hook::callAll('logged_in', $a->user);
-
 ### src/Render/FriendicaSmartyEngine.php
 
     Hook::callAll("template_vars", $arr);
diff --git a/doc/api.md b/doc/api.md
index a4ea985778..f3fae82014 100644
--- a/doc/api.md
+++ b/doc/api.md
@@ -20,9 +20,7 @@ Using an invalid method results in HTTP error 405 "Method Not Allowed".
 
 ### Authentication
 
-Friendica supports basic HTTP Auth and OAuth 1 to authenticate the user to the APIs.
-
-OAuth settings can be added by the user in web UI under [/settings/oauth/](/settings/oauth/).
+Friendica supports basic HTTP Auth and OAuth to authenticate the user to the APIs.
 
 ### Errors
 
diff --git a/include/api.php b/include/api.php
index b823b93df5..1223e1b2a5 100644
--- a/include/api.php
+++ b/include/api.php
@@ -174,7 +174,7 @@ function api_register_func($path, $func, $auth = false, $method = API_METHOD_ANY
 }
 
 /**
- * Log in user via OAuth1 or Simple HTTP Auth.
+ * Log in user via Simple HTTP Auth.
  * Simple Auth allow username in form of <pre>user@server</pre>, ignoring server part
  *
  * @param App $a App
diff --git a/src/Module/Api/Mastodon/Search.php b/src/Module/Api/Mastodon/Search.php
index f6b95ae923..63190151d7 100644
--- a/src/Module/Api/Mastodon/Search.php
+++ b/src/Module/Api/Mastodon/Search.php
@@ -58,7 +58,7 @@ class Search extends BaseApi
 			'offset'             => 0,     // Offset in search results. Used for pagination. Defaults to 0.
 			'following'          => false, // Only include accounts that the user is following. Defaults to false.
 		]);
-		
+
 		if (empty($request['q'])) {
 			DI::mstdnError()->UnprocessableEntity();
 		}
@@ -74,7 +74,7 @@ class Search extends BaseApi
 			$result['statuses'] = self::searchStatuses($uid, $request['q'], $request['account_id'], $request['max_id'], $request['min_id'], $limit, $request['offset']);
 		}
 		if ((empty($request['type']) || ($request['type'] == 'hashtags')) && (strpos($request['q'], '@') == false)) {
-			$result['hashtags'] = self::searchHashtags($request['q'], $request['exclude_unreviewed'], $limit, $request['offset']);
+			$result['hashtags'] = self::searchHashtags($request['q'], $request['exclude_unreviewed'], $limit, $request['offset'], $parameters['version']);
 		}
 
 		System::jsonExit($result);
@@ -175,7 +175,7 @@ class Search extends BaseApi
 		return $statuses;
 	}
 
-	private static function searchHashtags(string $q, bool $exclude_unreviewed, int $limit, int $offset)
+	private static function searchHashtags(string $q, bool $exclude_unreviewed, int $limit, int $offset, int $version)
 	{
 		$q = ltrim($q, '#');
 
@@ -187,7 +187,11 @@ class Search extends BaseApi
 
 		$hashtags = [];
 		foreach ($tags as $tag) {
-			$hashtags[] = new \Friendica\Object\Api\Mastodon\Tag(DI::baseUrl(), $tag);
+			if ($version == 1) {
+				$hashtags[] = $tag['name'];
+			} else {
+				$hashtags[] = new \Friendica\Object\Api\Mastodon\Tag(DI::baseUrl(), $tag);
+			}
 		}
 
 		return $hashtags;
diff --git a/src/Module/Api/Mastodon/Statuses/Card.php b/src/Module/Api/Mastodon/Statuses/Card.php
new file mode 100644
index 0000000000..ae42ea87bd
--- /dev/null
+++ b/src/Module/Api/Mastodon/Statuses/Card.php
@@ -0,0 +1,57 @@
+<?php
+/**
+ * @copyright Copyright (C) 2010-2021, the Friendica project
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace Friendica\Module\Api\Mastodon\Statuses;
+
+use Friendica\Core\System;
+use Friendica\Database\DBA;
+use Friendica\DI;
+use Friendica\Model\Post;
+use Friendica\Module\BaseApi;
+
+/**
+ * @see https://docs.joinmastodon.org/methods/statuses/
+ */
+class Card extends BaseApi
+{
+	/**
+	 * @param array $parameters
+	 * @throws \Friendica\Network\HTTPException\InternalServerErrorException
+	 */
+	public static function rawContent(array $parameters = [])
+	{
+		$uid = self::getCurrentUserID();
+
+		if (empty($parameters['id'])) {
+			DI::mstdnError()->UnprocessableEntity();
+		}
+
+		$request = self::getRequest([
+			'limit'    => 40, // Maximum number of results to return. Defaults to 40.
+		]);
+
+		$id = $parameters['id'];
+
+		$card = DI::mstdnCard()->createFromUriId($id);
+
+		System::jsonExit($card->toArray());
+	}
+}
diff --git a/static/routes.config.php b/static/routes.config.php
index bfa46831d2..6c61e577c2 100644
--- a/static/routes.config.php
+++ b/static/routes.config.php
@@ -131,6 +131,7 @@ return [
 			'/scheduled_statuses/{id:\d+}'       => [Module\Api\Mastodon\Unimplemented::class,            [R::GET, R::PUT, R::DELETE]], // not supported
 			'/statuses'                          => [Module\Api\Mastodon\Statuses::class,                 [        R::POST]],
 			'/statuses/{id:\d+}'                 => [Module\Api\Mastodon\Statuses::class,                 [R::GET, R::DELETE]],
+			'/statuses/{id:\d+}/card'            => [Module\Api\Mastodon\Statuses\Card::class,            [R::GET         ]],
 			'/statuses/{id:\d+}/context'         => [Module\Api\Mastodon\Statuses\Context::class,         [R::GET         ]],
 			'/statuses/{id:\d+}/reblogged_by'    => [Module\Api\Mastodon\Statuses\RebloggedBy::class,     [R::GET         ]],
 			'/statuses/{id:\d+}/favourited_by'   => [Module\Api\Mastodon\Statuses\FavouritedBy::class,    [R::GET         ]],
@@ -154,7 +155,7 @@ return [
 			'/timelines/tag/{hashtag}'           => [Module\Api\Mastodon\Timelines\Tag::class,            [R::GET         ]],
 			'/trends'                            => [Module\Api\Mastodon\Trends::class,                   [R::GET         ]],
 		],
-		'/v2' => [
+		'/v{version:\d+}' => [
 			'/search'                            => [Module\Api\Mastodon\Search::class,                   [R::GET         ]],
 		],
 		'/friendica' => [
diff --git a/view/templates/oauth_authorize_done.tpl b/view/templates/oauth_authorize_done.tpl
deleted file mode 100644
index 2e480e6411..0000000000
--- a/view/templates/oauth_authorize_done.tpl
+++ /dev/null
@@ -1,5 +0,0 @@
-
-<h1>{{$title}}</h1>
-
-<p>{{$info}}</p>
-<code>{{$code}}</code>
diff --git a/view/templates/settings/oauth_edit.tpl b/view/templates/settings/oauth_edit.tpl
deleted file mode 100644
index 86eb7663d6..0000000000
--- a/view/templates/settings/oauth_edit.tpl
+++ /dev/null
@@ -1,18 +0,0 @@
-
-<h1>{{$title}}</h1>
-
-<form method="POST">
-<input type='hidden' name='form_security_token' value='{{$form_security_token}}'>
-
-{{include file="field_input.tpl" field=$name}}
-{{include file="field_input.tpl" field=$key}}
-{{include file="field_input.tpl" field=$secret}}
-{{include file="field_input.tpl" field=$redirect}}
-{{include file="field_input.tpl" field=$icon}}
-
-<div class="settings-submit-wrapper">
-<input type="submit" name="submit" class="settings-submit" value="{{$submit}}" />
-<!-- <input type="submit" name="cancel" class="settings-submit" value="{{$cancel}}" /> -->
-</div>
-
-</form>
diff --git a/view/theme/frio/templates/settings/oauth_edit.tpl b/view/theme/frio/templates/settings/oauth_edit.tpl
deleted file mode 100644
index bd650bc082..0000000000
--- a/view/theme/frio/templates/settings/oauth_edit.tpl
+++ /dev/null
@@ -1,19 +0,0 @@
-<div class="generic-page-wrapper">
-<h2 class="heading">{{$title}}</h2>
-
-<form method="POST">
-	<input type='hidden' name='form_security_token' value='{{$form_security_token}}'>
-
-	{{include file="field_input.tpl" field=$name}}
-	{{include file="field_input.tpl" field=$key}}
-	{{include file="field_input.tpl" field=$secret}}
-	{{include file="field_input.tpl" field=$redirect}}
-	{{include file="field_input.tpl" field=$icon}}
-
-	<div class="form-group pull-right settings-submit-wrapper">
-		<button type="submit" name="submit" class="btn btn-primary" value="{{$submit}}">{{$submit}}</button>
-	</div>
-	<div class="clear"></div>
-
-</form>
-</div>
\ No newline at end of file