Merge pull request #9664 from annando/delete-contacts
Delete removed contacts
This commit is contained in:
commit
1414d43597
7 changed files with 58 additions and 14 deletions
|
@ -147,14 +147,25 @@ class APContact
|
||||||
$url = $apcontact['url'];
|
$url = $apcontact['url'];
|
||||||
}
|
}
|
||||||
|
|
||||||
$data = ActivityPub::fetchContent($url);
|
$curlResult = HTTPSignature::fetchRaw($url);
|
||||||
if (empty($data)) {
|
$failed = empty($curlResult) || empty($curlResult->getBody()) ||
|
||||||
|
(!$curlResult->isSuccess() && ($curlResult->getReturnCode() != 410));
|
||||||
|
|
||||||
|
if (!$failed) {
|
||||||
|
$data = json_decode($curlResult->getBody(), true);
|
||||||
|
$failed = empty($data) || !is_array($data);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$failed && ($curlResult->getReturnCode() == 410)) {
|
||||||
|
$data = ['@context' => ActivityPub::CONTEXT, 'id' => $url, 'type' => 'Tombstone'];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($failed) {
|
||||||
self::markForArchival($fetched_contact ?: []);
|
self::markForArchival($fetched_contact ?: []);
|
||||||
return $fetched_contact;
|
return $fetched_contact;
|
||||||
}
|
}
|
||||||
|
|
||||||
$compacted = JsonLD::compact($data);
|
$compacted = JsonLD::compact($data);
|
||||||
|
|
||||||
if (empty($compacted['@id'])) {
|
if (empty($compacted['@id'])) {
|
||||||
return $fetched_contact;
|
return $fetched_contact;
|
||||||
}
|
}
|
||||||
|
@ -207,8 +218,11 @@ class APContact
|
||||||
}
|
}
|
||||||
|
|
||||||
// Quit if none of the basic values are set
|
// Quit if none of the basic values are set
|
||||||
if (empty($apcontact['url']) || empty($apcontact['inbox']) || empty($apcontact['type'])) {
|
if (empty($apcontact['url']) || empty($apcontact['type']) || (($apcontact['type'] != 'Tombstone') && empty($apcontact['inbox']))) {
|
||||||
return $fetched_contact;
|
return $fetched_contact;
|
||||||
|
} elseif ($apcontact['type'] == 'Tombstone') {
|
||||||
|
// The "inbox" field must have a content
|
||||||
|
$apcontact['inbox'] = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
// Quit if this doesn't seem to be an account at all
|
// Quit if this doesn't seem to be an account at all
|
||||||
|
|
|
@ -724,7 +724,7 @@ class Contact
|
||||||
{
|
{
|
||||||
// We want just to make sure that we don't delete our "self" contact
|
// We want just to make sure that we don't delete our "self" contact
|
||||||
$contact = DBA::selectFirst('contact', ['uid'], ['id' => $id, 'self' => false]);
|
$contact = DBA::selectFirst('contact', ['uid'], ['id' => $id, 'self' => false]);
|
||||||
if (!DBA::isResult($contact) || !intval($contact['uid'])) {
|
if (!DBA::isResult($contact)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1762,6 +1762,17 @@ class Contact
|
||||||
DBA::update('contact', $fields, ['id' => $cids]);
|
DBA::update('contact', $fields, ['id' => $cids]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function deleteContactByUrl(string $url)
|
||||||
|
{
|
||||||
|
// Update contact data for all users
|
||||||
|
$condition = ['self' => false, 'nurl' => Strings::normaliseLink($url)];
|
||||||
|
$contacts = DBA::select('contact', ['id', 'uid'], $condition);
|
||||||
|
while ($contact = DBA::fetch($contacts)) {
|
||||||
|
Logger::info('Deleting contact', ['id' => $contact['id'], 'uid' => $contact['uid'], 'url' => $url]);
|
||||||
|
self::remove($contact['id']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper function for "updateFromProbe". Updates personal and public contact
|
* Helper function for "updateFromProbe". Updates personal and public contact
|
||||||
*
|
*
|
||||||
|
@ -1914,6 +1925,15 @@ class Contact
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!empty($ret['account-type']) && $ret['account-type'] == User::ACCOUNT_TYPE_DELETED) {
|
||||||
|
Logger::info('Deleted account', ['id' => $id, 'url' => $ret['url'], 'ret' => $ret]);
|
||||||
|
self::remove($id);
|
||||||
|
|
||||||
|
// Delete all contacts with the same URL
|
||||||
|
self::deleteContactByUrl($ret['url']);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
$uid = $contact['uid'];
|
$uid = $contact['uid'];
|
||||||
unset($contact['uid']);
|
unset($contact['uid']);
|
||||||
|
|
||||||
|
|
|
@ -97,6 +97,7 @@ class User
|
||||||
const ACCOUNT_TYPE_NEWS = 2;
|
const ACCOUNT_TYPE_NEWS = 2;
|
||||||
const ACCOUNT_TYPE_COMMUNITY = 3;
|
const ACCOUNT_TYPE_COMMUNITY = 3;
|
||||||
const ACCOUNT_TYPE_RELAY = 4;
|
const ACCOUNT_TYPE_RELAY = 4;
|
||||||
|
const ACCOUNT_TYPE_DELETED = 127;
|
||||||
/**
|
/**
|
||||||
* @}
|
* @}
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -104,7 +104,7 @@ class Proxy extends BaseModule
|
||||||
|
|
||||||
// It shouldn't happen but it does - spaces in URL
|
// It shouldn't happen but it does - spaces in URL
|
||||||
$request['url'] = str_replace(' ', '+', $request['url']);
|
$request['url'] = str_replace(' ', '+', $request['url']);
|
||||||
$fetchResult = HTTPSignature::fetchRaw($request['url'], local_user(), true, ['timeout' => 10]);
|
$fetchResult = HTTPSignature::fetchRaw($request['url'], local_user(), ['timeout' => 10]);
|
||||||
$img_str = $fetchResult->getBody();
|
$img_str = $fetchResult->getBody();
|
||||||
|
|
||||||
// If there is an error then return a blank image
|
// If there is an error then return a blank image
|
||||||
|
|
|
@ -68,7 +68,7 @@ class ActivityPub
|
||||||
'manuallyApprovesFollowers' => 'as:manuallyApprovesFollowers',
|
'manuallyApprovesFollowers' => 'as:manuallyApprovesFollowers',
|
||||||
'sensitive' => 'as:sensitive', 'Hashtag' => 'as:Hashtag',
|
'sensitive' => 'as:sensitive', 'Hashtag' => 'as:Hashtag',
|
||||||
'directMessage' => 'litepub:directMessage']];
|
'directMessage' => 'litepub:directMessage']];
|
||||||
const ACCOUNT_TYPES = ['Person', 'Organization', 'Service', 'Group', 'Application'];
|
const ACCOUNT_TYPES = ['Person', 'Organization', 'Service', 'Group', 'Application', 'Tombstone'];
|
||||||
/**
|
/**
|
||||||
* Checks if the web request is done for the AP protocol
|
* Checks if the web request is done for the AP protocol
|
||||||
*
|
*
|
||||||
|
@ -113,6 +113,9 @@ class ActivityPub
|
||||||
case 'Application':
|
case 'Application':
|
||||||
$accounttype = User::ACCOUNT_TYPE_RELAY;
|
$accounttype = User::ACCOUNT_TYPE_RELAY;
|
||||||
break;
|
break;
|
||||||
|
case 'Tombstone':
|
||||||
|
$accounttype = User::ACCOUNT_TYPE_DELETED;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $accounttype;
|
return $accounttype;
|
||||||
|
|
|
@ -376,8 +376,7 @@ class HTTPSignature
|
||||||
*/
|
*/
|
||||||
public static function fetch($request, $uid)
|
public static function fetch($request, $uid)
|
||||||
{
|
{
|
||||||
$opts = ['accept_content' => 'application/activity+json, application/ld+json'];
|
$curlResult = self::fetchRaw($request, $uid);
|
||||||
$curlResult = self::fetchRaw($request, $uid, false, $opts);
|
|
||||||
|
|
||||||
if (empty($curlResult)) {
|
if (empty($curlResult)) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -410,7 +409,7 @@ class HTTPSignature
|
||||||
* @return object CurlResult
|
* @return object CurlResult
|
||||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||||
*/
|
*/
|
||||||
public static function fetchRaw($request, $uid = 0, $binary = false, $opts = [])
|
public static function fetchRaw($request, $uid = 0, $opts = ['accept_content' => 'application/activity+json, application/ld+json'])
|
||||||
{
|
{
|
||||||
$header = [];
|
$header = [];
|
||||||
|
|
||||||
|
|
|
@ -31,15 +31,21 @@ use Friendica\Model\Photo;
|
||||||
*/
|
*/
|
||||||
class RemoveContact {
|
class RemoveContact {
|
||||||
public static function execute($id) {
|
public static function execute($id) {
|
||||||
|
|
||||||
// Only delete if the contact is to be deleted
|
// Only delete if the contact is to be deleted
|
||||||
$contact = DBA::selectFirst('contact', ['uid'], ['deleted' => true, 'id' => $id]);
|
$contact = DBA::selectFirst('contact', ['uid'], ['deleted' => true, 'id' => $id]);
|
||||||
if (!DBA::isResult($contact)) {
|
if (!DBA::isResult($contact)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Logger::info('Start deleting contact', ['id' => $id]);
|
||||||
// Now we delete the contact and all depending tables
|
// Now we delete the contact and all depending tables
|
||||||
$condition = ['uid' => $contact['uid'], 'contact-id' => $id];
|
if ($contact['uid'] == 0) {
|
||||||
|
DBA::delete('post-tag', ['cid' => $id]);
|
||||||
|
$condition = ["`author-id` = ? OR `owner-id` = ? OR `causer-id` = ? OR `contact-id` = ?",
|
||||||
|
$id, $id, $id, $id];
|
||||||
|
} else {
|
||||||
|
$condition = ['uid' => $contact['uid'], 'contact-id' => $id];
|
||||||
|
}
|
||||||
do {
|
do {
|
||||||
$items = Item::select(['id', 'guid'], $condition, ['limit' => 100]);
|
$items = Item::select(['id', 'guid'], $condition, ['limit' => 100]);
|
||||||
while ($item = Item::fetch($items)) {
|
while ($item = Item::fetch($items)) {
|
||||||
|
@ -49,7 +55,8 @@ class RemoveContact {
|
||||||
DBA::close($items);
|
DBA::close($items);
|
||||||
} while (Item::exists($condition));
|
} while (Item::exists($condition));
|
||||||
|
|
||||||
Photo::delete(['uid' => $contact['uid'], 'contact-id' => $id]);
|
Photo::delete(['contact-id' => $id]);
|
||||||
DBA::delete('contact', ['id' => $id]);
|
$ret = DBA::delete('contact', ['id' => $id]);
|
||||||
|
Logger::info('Deleted contact', ['id' => $id, 'result' => $ret]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue