Merge remote-tracking branch 'upstream/2021.06-rc' into public-timeline

This commit is contained in:
Michael 2021-06-16 21:01:20 +00:00
commit ebd4f59d02
34 changed files with 273 additions and 103 deletions

View file

@ -77,6 +77,7 @@ class Followers extends BaseApi
$followers = DBA::select('contact-relation', ['relation-cid'], $condition, $parameters);
while ($follower = DBA::fetch($followers)) {
self::setBoundaries($follower['relation-cid']);
$accounts[] = DI::mstdnAccount()->createFromContactId($follower['relation-cid'], $uid);
}
DBA::close($followers);
@ -85,6 +86,7 @@ class Followers extends BaseApi
array_reverse($accounts);
}
self::setLinkHeader();
System::jsonExit($accounts);
}
}

View file

@ -77,6 +77,7 @@ class Following extends BaseApi
$followers = DBA::select('contact-relation', ['cid'], $condition, $parameters);
while ($follower = DBA::fetch($followers)) {
self::setBoundaries($follower['cid']);
$accounts[] = DI::mstdnAccount()->createFromContactId($follower['cid'], $uid);
}
DBA::close($followers);
@ -85,6 +86,7 @@ class Following extends BaseApi
array_reverse($accounts);
}
self::setLinkHeader();
System::jsonExit($accounts);
}
}

View file

@ -108,6 +108,7 @@ class Statuses extends BaseApi
$statuses = [];
while ($item = Post::fetch($items)) {
self::setBoundaries($item['uri-id']);
$statuses[] = DI::mstdnStatus()->createFromUriId($item['uri-id'], $uid);
}
DBA::close($items);
@ -116,6 +117,7 @@ class Statuses extends BaseApi
array_reverse($statuses);
}
self::setLinkHeader();
System::jsonExit($statuses);
}
}

View file

@ -77,6 +77,7 @@ class Blocks extends BaseApi
$followers = DBA::select('user-contact', ['cid'], $condition, $parameters);
while ($follower = DBA::fetch($followers)) {
self::setBoundaries($follower['cid']);
$accounts[] = DI::mstdnAccount()->createFromContactId($follower['cid'], $uid);
}
DBA::close($followers);
@ -85,6 +86,7 @@ class Blocks extends BaseApi
array_reverse($accounts);
}
self::setLinkHeader();
System::jsonExit($accounts);
}
}

View file

@ -72,6 +72,7 @@ class Bookmarks extends BaseApi
$statuses = [];
while ($item = Post::fetch($items)) {
self::setBoundaries($item['uri-id']);
$statuses[] = DI::mstdnStatus()->createFromUriId($item['uri-id'], $uid);
}
DBA::close($items);
@ -80,6 +81,7 @@ class Bookmarks extends BaseApi
array_reverse($statuses);
}
self::setLinkHeader();
System::jsonExit($statuses);
}
}

View file

@ -85,6 +85,7 @@ class Conversations extends BaseApi
$conversations = [];
while ($conv = DBA::fetch($convs)) {
self::setBoundaries($conv['id']);
$conversations[] = DI::mstdnConversation()->CreateFromConvId($conv['id']);
}
@ -94,6 +95,7 @@ class Conversations extends BaseApi
array_reverse($conversations);
}
self::setLinkHeader();
System::jsonExit($conversations);
}
}

View file

@ -70,6 +70,7 @@ class Favourited extends BaseApi
$statuses = [];
while ($item = Post::fetch($items)) {
self::setBoundaries($item['thr-parent-id']);
$statuses[] = DI::mstdnStatus()->createFromUriId($item['thr-parent-id'], $uid);
}
DBA::close($items);
@ -78,6 +79,7 @@ class Favourited extends BaseApi
array_reverse($statuses);
}
self::setLinkHeader();
System::jsonExit($statuses);
}
}

View file

@ -92,8 +92,6 @@ class FollowRequests extends BaseApi
'limit' => 40, // Maximum number of results to return. Defaults to 40. Paginate using the HTTP Link header.
]);
$baseUrl = DI::baseUrl();
$introductions = DI::intro()->selectByBoundaries(
['`uid` = ? AND NOT `ignore`', $uid],
['order' => ['id' => 'DESC']],
@ -106,6 +104,7 @@ class FollowRequests extends BaseApi
foreach ($introductions as $key => $introduction) {
try {
self::setBoundaries($introduction->id);
$return[] = DI::mstdnFollowRequest()->createFromIntroduction($introduction);
} catch (HTTPException\InternalServerErrorException $exception) {
DI::intro()->delete($introduction);
@ -113,22 +112,7 @@ class FollowRequests extends BaseApi
}
}
$base_query = [];
if (isset($_GET['limit'])) {
$base_query['limit'] = $request['limit'];
}
$links = [];
if ($introductions->getTotalCount() > $request['limit']) {
$links[] = '<' . $baseUrl->get() . '/api/v1/follow_requests?' . http_build_query($base_query + ['max_id' => $introductions[count($introductions) - 1]->id]) . '>; rel="next"';
}
if (count($introductions)) {
$links[] = '<' . $baseUrl->get() . '/api/v1/follow_requests?' . http_build_query($base_query + ['min_id' => $introductions[0]->id]) . '>; rel="prev"';
}
header('Link: ' . implode(', ', $links));
self::setLinkHeader();
System::jsonExit($return);
}
}

View file

@ -95,6 +95,7 @@ class Accounts extends BaseApi
$members = DBA::select('group_member', ['contact-id'], $condition, $params);
while ($member = DBA::fetch($members)) {
self::setBoundaries($member['contact-id']);
$accounts[] = DI::mstdnAccount()->createFromContactId($member['contact-id'], $uid);
}
DBA::close($members);
@ -103,6 +104,7 @@ class Accounts extends BaseApi
array_reverse($accounts);
}
self::setLinkHeader();
System::jsonExit($accounts);
}
}

View file

@ -77,6 +77,7 @@ class Mutes extends BaseApi
$followers = DBA::select('user-contact', ['cid'], $condition, $parameters);
while ($follower = DBA::fetch($followers)) {
self::setBoundaries($follower['cid']);
$accounts[] = DI::mstdnAccount()->createFromContactId($follower['cid'], $uid);
}
DBA::close($followers);
@ -85,6 +86,7 @@ class Mutes extends BaseApi
array_reverse($accounts);
}
self::setLinkHeader();
System::jsonExit($accounts);
}
}

View file

@ -128,6 +128,7 @@ class Notifications extends BaseApi
$notify = DBA::select('notification', ['id'], $condition, $params);
while ($notification = DBA::fetch($notify)) {
self::setBoundaries($notification['id']);
$entry = DI::mstdnNotification()->createFromNotificationId($notification['id']);
if (!empty($entry)) {
$notifications[] = $entry;
@ -138,6 +139,7 @@ class Notifications extends BaseApi
array_reverse($notifications);
}
self::setLinkHeader();
System::jsonExit($notifications);
}
}

View file

@ -162,6 +162,7 @@ class Search extends BaseApi
$statuses = [];
while ($item = Post::fetch($items)) {
self::setBoundaries($item['uri-id']);
$statuses[] = DI::mstdnStatus()->createFromUriId($item['uri-id'], $uid);
}
DBA::close($items);
@ -170,6 +171,7 @@ class Search extends BaseApi
array_reverse($statuses);
}
self::setLinkHeader();
return $statuses;
}

View file

@ -71,6 +71,7 @@ class Direct extends BaseApi
$statuses = [];
while ($mail = DBA::fetch($mails)) {
self::setBoundaries($mail['uri-id']);
$statuses[] = DI::mstdnStatus()->createFromMailId($mail['id']);
}
@ -78,6 +79,7 @@ class Direct extends BaseApi
array_reverse($statuses);
}
self::setLinkHeader();
System::jsonExit($statuses);
}
}

View file

@ -93,6 +93,7 @@ class Home extends BaseApi
$statuses = [];
while ($item = Post::fetch($items)) {
self::setBoundaries($item['uri-id']);
$statuses[] = DI::mstdnStatus()->createFromUriId($item['uri-id'], $uid);
}
DBA::close($items);
@ -101,6 +102,7 @@ class Home extends BaseApi
array_reverse($statuses);
}
self::setLinkHeader();
System::jsonExit($statuses);
}
}

View file

@ -98,6 +98,7 @@ class ListTimeline extends BaseApi
$statuses = [];
while ($item = Post::fetch($items)) {
self::setBoundaries($item['uri-id']);
$statuses[] = DI::mstdnStatus()->createFromUriId($item['uri-id'], $uid);
}
DBA::close($items);
@ -106,6 +107,7 @@ class ListTimeline extends BaseApi
array_reverse($statuses);
}
self::setLinkHeader();
System::jsonExit($statuses);
}
}

View file

@ -99,6 +99,7 @@ class PublicTimeline extends BaseApi
$statuses = [];
while ($item = Post::fetch($items)) {
self::setBoundaries($item['uri-id']);
$statuses[] = DI::mstdnStatus()->createFromUriId($item['uri-id'], $uid);
}
DBA::close($items);
@ -107,6 +108,7 @@ class PublicTimeline extends BaseApi
array_reverse($statuses);
}
self::setLinkHeader();
System::jsonExit($statuses);
}
}

View file

@ -107,6 +107,7 @@ class Tag extends BaseApi
$statuses = [];
while ($item = Post::fetch($items)) {
self::setBoundaries($item['uri-id']);
$statuses[] = DI::mstdnStatus()->createFromUriId($item['uri-id'], $uid);
}
DBA::close($items);
@ -115,6 +116,7 @@ class Tag extends BaseApi
array_reverse($statuses);
}
self::setLinkHeader();
System::jsonExit($statuses);
}
}

View file

@ -44,6 +44,16 @@ class BaseApi extends BaseModule
*/
protected static $format = 'json';
/**
* @var array
*/
protected static $boundaries = [];
/**
* @var array
*/
protected static $request = [];
public static function init(array $parameters = [])
{
$arguments = DI::args();
@ -129,6 +139,11 @@ class BaseApi extends BaseModule
$httpinput = HTTPInputData::process();
$input = array_merge($httpinput['variables'], $httpinput['files'], $_REQUEST);
self::$request = $input;
self::$boundaries = [];
unset(self::$request['pagename']);
$request = [];
foreach ($defaults as $parameter => $defaultvalue) {
@ -160,6 +175,55 @@ class BaseApi extends BaseModule
return $request;
}
/**
* Set boundaries for the "link" header
* @param array $boundaries
* @param int $id
* @return array
*/
protected static function setBoundaries(int $id)
{
if (!isset(self::$boundaries['min'])) {
self::$boundaries['min'] = $id;
}
if (!isset(self::$boundaries['max'])) {
self::$boundaries['max'] = $id;
}
self::$boundaries['min'] = min(self::$boundaries['min'], $id);
self::$boundaries['max'] = max(self::$boundaries['max'], $id);
}
/**
* Set the "link" header with "next" and "prev" links
* @return void
*/
protected static function setLinkHeader()
{
if (empty(self::$boundaries)) {
return;
}
$request = self::$request;
unset($request['min_id']);
unset($request['max_id']);
unset($request['since_id']);
$prev_request = $next_request = $request;
$prev_request['min_id'] = self::$boundaries['max'];
$next_request['max_id'] = self::$boundaries['min'];
$command = DI::baseUrl() . '/' . DI::args()->getCommand();
$prev = $command . '?' . http_build_query($prev_request);
$next = $command . '?' . http_build_query($next_request);
header('Link: <' . $next . '>; rel="next", <' . $prev . '>; rel="prev"');
}
/**
* Get current application token
*

View file

@ -41,11 +41,12 @@ class Authorize extends BaseApi
public static function rawContent(array $parameters = [])
{
$request = self::getRequest([
'response_type' => '',
'client_id' => '',
'force_login' => '', // Forces the user to re-login, which is necessary for authorizing with multiple accounts from the same instance.
'response_type' => '', // Should be set equal to "code".
'client_id' => '', // Client ID, obtained during app registration.
'client_secret' => '', // Isn't normally provided. We will use it if present.
'redirect_uri' => '',
'scope' => 'read',
'redirect_uri' => '', // Set a URI to redirect the user to. If this parameter is set to "urn:ietf:wg:oauth:2.0:oob" then the authorization code will be shown instead. Must match one of the redirect URIs declared during app registration.
'scope' => 'read', // List of requested OAuth scopes, separated by spaces (or by pluses, if using query parameters). Must be a subset of scopes declared during app registration. If not provided, defaults to "read".
'state' => '',
]);

View file

@ -21,6 +21,10 @@
namespace Friendica\Module\OAuth;
use Friendica\Core\Logger;
use Friendica\Core\System;
use Friendica\Database\DBA;
use Friendica\DI;
use Friendica\Module\BaseApi;
/**
@ -30,6 +34,20 @@ class Revoke extends BaseApi
{
public static function post(array $parameters = [])
{
self::unsupported('post');
$request = self::getRequest([
'client_id' => '', // Client ID, obtained during app registration
'client_secret' => '', // Client secret, obtained during app registration
'token' => '', // The previously obtained token, to be invalidated
]);
$condition = ['client_id' => $request['client_id'], 'client_secret' => $request['client_secret'], 'access_token' => $request['token']];
$token = DBA::selectFirst('application-view', ['id'], $condition);
if (empty($token['id'])) {
Logger::warning('Token not found', $condition);
DI::mstdnError()->Unauthorized();
}
DBA::delete('application-token', ['application-id' => $token['id']]);
System::jsonExit([]);
}
}

View file

@ -37,16 +37,23 @@ class Token extends BaseApi
public static function post(array $parameters = [])
{
$request = self::getRequest([
'grant_type' => '',
'code' => '',
'redirect_uri' => '',
'client_id' => '',
'client_secret' => '',
'client_id' => '', // Client ID, obtained during app registration
'client_secret' => '', // Client secret, obtained during app registration
'redirect_uri' => '', // Set a URI to redirect the user to. If this parameter is set to "urn:ietf:wg:oauth:2.0:oob" then the token will be shown instead. Must match one of the redirect URIs declared during app registration.
'scope' => 'read', // List of requested OAuth scopes, separated by spaces. Must be a subset of scopes declared during app registration. If not provided, defaults to "read".
'code' => '', // A user authorization code, obtained via /oauth/authorize
'grant_type' => '', // Set equal to "authorization_code" if code is provided in order to gain user-level access. Otherwise, set equal to "client_credentials" to obtain app-level access only.
]);
// AndStatus transmits the client data in the AUTHORIZATION header field, see https://github.com/andstatus/andstatus/issues/530
if (empty($request['client_id']) && !empty($_SERVER['HTTP_AUTHORIZATION']) && (substr($_SERVER['HTTP_AUTHORIZATION'], 0, 6) == 'Basic ')) {
$datapair = explode(':', base64_decode(trim(substr($_SERVER['HTTP_AUTHORIZATION'], 6))));
$authorization = $_SERVER['HTTP_AUTHORIZATION'] ?? '';
if (empty($authorization)) {
// workaround for HTTP-auth in CGI mode
$authorization = $_SERVER['REDIRECT_REMOTE_USER'] ?? '';
}
if (empty($request['client_id']) && substr($authorization, 0, 6) == 'Basic ') {
$datapair = explode(':', base64_decode(trim(substr($authorization, 6))));
if (count($datapair) == 2) {
$request['client_id'] = $datapair[0];
$request['client_secret'] = $datapair[1];

View file

@ -86,8 +86,6 @@ class Index extends BaseSettings
return;
}
$namechanged = $profile['name'] != $name;
$about = Strings::escapeTags(trim($_POST['about']));
$address = Strings::escapeTags(trim($_POST['address']));
$locality = Strings::escapeTags(trim($_POST['locality']));
@ -114,8 +112,7 @@ class Index extends BaseSettings
DI::profileField()->saveCollection($profileFields);
$result = DBA::update(
'profile',
$result = Profile::update(
[
'name' => $name,
'about' => $about,
@ -130,26 +127,13 @@ class Index extends BaseSettings
'pub_keywords' => $pub_keywords,
'prv_keywords' => $prv_keywords,
],
['uid' => local_user()]
local_user()
);
if (!$result) {
notice(DI::l10n()->t('Profile couldn\'t be updated.'));
return;
}
if ($namechanged) {
DBA::update('user', ['username' => $name], ['uid' => local_user()]);
}
Contact::updateSelfFromUserID(local_user());
// Update global directory in background
if (Session::get('my_url') && strlen(DI::config()->get('system', 'directory'))) {
Worker::add(PRIORITY_LOW, 'Directory', Session::get('my_url'));
}
Worker::add(PRIORITY_LOW, 'ProfileUpdate', local_user());
}
public static function content(array $parameters = [])

View file

@ -28,6 +28,7 @@ use Friendica\Database\DBA;
use Friendica\DI;
use Friendica\Model\Contact;
use Friendica\Model\Photo;
use Friendica\Model\Profile;
use Friendica\Module\BaseSettings;
use Friendica\Network\HTTPException;
@ -137,12 +138,9 @@ class Crop extends BaseSettings
Contact::updateSelfFromUserID(local_user(), true);
info(DI::l10n()->t('Shift-reload the page or clear browser cache if the new photo does not display immediately.'));
// Update global directory in background
if ($path && strlen(DI::config()->get('system', 'directory'))) {
Worker::add(PRIORITY_LOW, 'Directory', DI::baseUrl()->get() . '/' . $path);
}
Worker::add(PRIORITY_LOW, 'ProfileUpdate', local_user());
// Update global directory in background
Profile::publishUpdate(local_user());
} else {
notice(DI::l10n()->t('Unable to process image'));
}
@ -183,9 +181,7 @@ class Crop extends BaseSettings
Contact::updateSelfFromUserID(local_user(), true);
// Update global directory in background
if (Session::get('my_url') && strlen(DI::config()->get('system', 'directory'))) {
Worker::add(PRIORITY_LOW, 'Directory', Session::get('my_url'));
}
Profile::publishUpdate(local_user());
info(DI::l10n()->t('Profile picture successfully updated.'));