Skip to content
Snippets Groups Projects
Commit 9aaad695 authored by Keegan Rankin's avatar Keegan Rankin Committed by Kristof De Jaeger
Browse files

Issue #3344797 by MegaKeegMan: Syndicate all content from a dedicated activity pub user

parent 9d5ab789
No related branches found
Tags 1.0.0-alpha17
1 merge request!20Issue #3344797: Syndicate all content from a dedicated activity pub user
......@@ -15,6 +15,11 @@ allow users to view the context:
title: 'Allow users to view the context'
description: 'Add or update the context of an Activity on the form. If not enabled, the form element will be hidden.'
publish to site-wide actor:
title: 'Publish to site-wide actor'
description: 'Allows user to publish to the ActivityPub account of a configured site-wide user if they have not enabled ActivityPub for their own account.'
resolve remote activitypub activities and actors:
title: 'Allow users to resolve remote activities and actors'
description: 'Allow users to resolve remote activities and actors. If not enabled, the remote lookup in search form will not be possible.'
......@@ -112,6 +112,9 @@ activitypub.settings:
attachment_content_style:
type: string
label: 'Attachment content image style'
site_wide_uid:
type: integer
label: 'Site-wide user'
process_outbox_handler:
type: string
label: 'Process outbox handler'
......
......@@ -214,6 +214,12 @@ class ActivityPubSettingsForm extends ConfigFormBase {
'#open' => TRUE
];
$form['outbox']['site_wide_uid'] = [
'#title' => $this->t('Site-wide user'),
'#type' => 'number',
'#default_value' => $config->get('site_wide_uid'),
];
$form['outbox']['process_outbox_handler'] = [
'#title' => $this->t('Send activities'),
'#type' => 'radios',
......@@ -360,6 +366,7 @@ class ActivityPubSettingsForm extends ConfigFormBase {
->set('log_followee_check', $form_state->getValue('log_followee_check'))
->set('log_error_signature', $form_state->getValue('log_error_signature'))
->set('log_ignore_error_signature', $form_state->getValue('log_ignore_error_signature'))
->set('site_wide_uid', $form_state->getValue('site_wide_uid'))
->save();
Cache::invalidateTags(['rendered']);
parent::submitForm($form, $form_state);
......
......@@ -280,7 +280,18 @@ class ActivityPubFormAlter implements ActivityPubFormAlterInterface {
*/
public function addActivityPubOutboxFormElement(array &$form, FormStateInterface $form_state, EntityInterface $entity) {
$config = \Drupal::configFactory()->getEditable('activitypub.settings');
$actor = $this->actorStorage->loadActorByEntityIdAndType($this->currentUser->id(), 'person');
// Check if a site-wide actor is configured and the current user has the permission to publish.
if (!$actor) {
$site_wide_uid = $config->get('site_wide_uid');
if ($site_wide_uid && $this->currentUser->hasPermission('publish to site-wide actor')) {
$actor = $this->actorStorage->loadActorByEntityIdAndType($site_wide_uid, 'person');
}
}
if (!$actor) {
return;
}
......
......@@ -69,7 +69,7 @@ class ActivityPubOutbox implements ActivityPubOutboxInterface {
/**
* {@inheritdoc}
*/
public function createActivity(string $type, EntityInterface $entity, ActivityPubActorInterface $actor = NULL, int $visibility = ActivityPubActivityInterface::VISIBILITY_PUBLIC, string $to = '') {
public function createActivity(string $type, EntityInterface $entity, ActivityPubActorInterface $actor, int $visibility = ActivityPubActivityInterface::VISIBILITY_PUBLIC, string $to = '') {
/** @var \Drupal\activitypub\Entity\ActivityPubTypeInterface $activityPubType */
$activityPubType = $this->typeStorage->load($type);
......@@ -77,18 +77,7 @@ class ActivityPubOutbox implements ActivityPubOutboxInterface {
return;
}
$uid = 0;
if (method_exists($entity, 'getOwnerId')) {
$uid = $entity->getOwnerId();
}
if (!$actor) {
$actor = $this->actorStorage->loadActorByEntityIdAndType($uid, 'person');
}
if (!$actor && !$uid) {
return;
}
$uid = $actor->getOwnerId();
$values = [
'collection' => 'outbox',
......@@ -131,4 +120,4 @@ class ActivityPubOutbox implements ActivityPubOutboxInterface {
}
}
}
\ No newline at end of file
}
......@@ -15,14 +15,14 @@ interface ActivityPubOutboxInterface {
* The ActivityPub type
* @param EntityInterface $entity
* The entity
* @param \Drupal\activitypub\Entity\ActivityPubActorInterface|null $actor
* @param \Drupal\activitypub\Entity\ActivityPubActorInterface $actor
* The actor
* @param int $visibility
* The post privacy.
* @param string $to
* Extra send parameter.
*/
public function createActivity(string $type, EntityInterface $entity, ActivityPubActorInterface $actor = NULL, int $visibility = ActivityPubActivityInterface::VISIBILITY_PUBLIC, string $to = '');
public function createActivity(string $type, EntityInterface $entity, ActivityPubActorInterface $actor, int $visibility = ActivityPubActivityInterface::VISIBILITY_PUBLIC, string $to = '');
/**
* Update outbox activity.
......@@ -31,4 +31,4 @@ interface ActivityPubOutboxInterface {
*/
public function updateActivity(ActivityPubActivityInterface $activity);
}
\ No newline at end of file
}
......@@ -78,6 +78,13 @@ abstract class ActivityPubTestBase extends BrowserTestBase {
*/
protected $authenticatedUserTwo;
/**
* An authenticated user with less permissions.
*
* @var \Drupal\user\UserInterface
*/
protected $authenticatedUserThree;
/**
* The authenticated user permissions.
*
......@@ -88,6 +95,7 @@ abstract class ActivityPubTestBase extends BrowserTestBase {
'administer nodes',
'bypass node access',
'access user profiles',
'publish to site-wide actor',
];
/**
......@@ -111,6 +119,10 @@ abstract class ActivityPubTestBase extends BrowserTestBase {
$this->adminUser = $this->createUser([], 'administrator', TRUE);
$this->authenticatedUserOne = $this->createUser($this->authenticatedUserPermissions, 'fediverseOne');
$this->authenticatedUserTwo = $this->createUser($this->authenticatedUserPermissions, 'fediverseTwo');
$this->authenticatedUserThree = $this->createUser($this->authenticatedUserPermissions, 'nonFediverse');
// Set site-wide actor
$this->setSitewideActor();
$this->httpClient = $this->container->get('http_client_factory')
->fromOptions(['base_uri' => $this->baseUrl]);
......@@ -559,7 +571,7 @@ abstract class ActivityPubTestBase extends BrowserTestBase {
];
$this->drupalGet('admin/config/services/activitypub');
$this->submitForm($edit, 'Save configuration');
$this->drupalLogout();;
$this->drupalLogout();
}
/**
......@@ -572,7 +584,21 @@ abstract class ActivityPubTestBase extends BrowserTestBase {
];
$this->drupalGet('admin/config/services/activitypub');
$this->submitForm($edit, 'Save configuration');
$this->drupalLogout();;
$this->drupalLogout();
}
/**
* Set the user id of the site-wide actor.
*/
protected function setSitewideActor()
{
$this->drupalLogin($this->adminUser);
$edit = [
'site_wide_uid' => $this->authenticatedUserOne->id(),
];
$this->drupalGet('admin/config/services/activitypub');
$this->submitForm($edit, 'Save configuration');
$this->drupalLogout();
}
/**
......
......@@ -190,6 +190,99 @@ class OutboxTest extends ActivityPubTestBase {
self::assertEquals('<p>' . $node->get('body')->value . '</p>', $json['object']['content']);
}
/**
* Test to from sitewide functionality.
*/
public function testToFromSitewide()
{
$assert_session = $this->assertSession();
$this->config('activitypub.settings')->set('log_success_signature', TRUE)->save();
/** @var \Drupal\activitypub\Entity\Storage\ActivityPubActorStorageInterface $storage */
$storage = \Drupal::entityTypeManager()->getStorage('activitypub_activity');
// Setup ActivityPub actors.
$this->enableActivityPub($assert_session, TRUE);
$this->drupalLogout();
// Set outbox handler.
$this->setOutboxHandler();
$actor_href = Url::fromRoute('activitypub.user.self', ['user' => $this->authenticatedUserOne->id(), 'activitypub_actor' => $this->accountNameOne], ['absolute' => TRUE])->toString();
$object_href = Url::fromRoute('activitypub.user.self', ['user' => $this->authenticatedUserTwo->id(), 'activitypub_actor' => $this->accountNameTwo], ['absolute' => TRUE])->toString();
// Create type.
$this->createType('Create', 'page', 'Note');
// Login.
$this->drupalLogin($this->authenticatedUserThree);
// Unpublished one should not create a queue item.
$this->drupalGet('node/add/page');
$edit = [
'title[0][value]' => 'Sending to someone',
'body[0][value]' => 'Hello unknown follower!',
'activitypub_create' => 'map',
'activitypub_to' => $object_href,
'status[value]' => FALSE,
];
$this->submitForm($edit, 'Save');
$count = \Drupal::queue(ACTIVITYPUB_OUTBOX_QUEUE)->numberOfItems();
self::assertEquals(0, $count);
// Send to outbox.
$this->drupalGet('node/add/page');
$edit = [
'title[0][value]' => 'Sending to someone',
'body[0][value]' => 'Hello unknown follower!',
'activitypub_create' => 'map',
'activitypub_to' => $object_href,
];
$this->submitForm($edit, 'Save');
$this->drupalLogout();
/** @var \Drupal\node\NodeInterface $node */
$node = \Drupal::entityTypeManager()->getStorage('node')->load(2);
$count = \Drupal::queue(ACTIVITYPUB_OUTBOX_QUEUE)->numberOfItems();
self::assertEquals(1, $count);
/** @var \Drupal\activitypub\Entity\ActivityPubActivityInterface $activity */
$activity = $storage->load(1);
$build = $activity->buildActivity();
self::assertTrue(in_array(ActivityPubActivityInterface::PUBLIC_URL, $build['to']));
self::assertTrue(in_array($object_href, $build['to']));
$this->runOutboxQueue();
// Verify that signature was ok.
$messages = \Drupal::database()->select('watchdog', 'w')
->fields('w')
->range(1, 1)
->orderBy('wid', 'DESC')
->execute()
->fetchAll();
self::assertEquals('Signature verified for id @id', $messages[0]->message);
$count = \Drupal::queue(ACTIVITYPUB_OUTBOX_QUEUE)->numberOfItems();
self::assertEquals(0, $count);
//$this->viewActivityOverview();
/** @var \Drupal\activitypub\Entity\ActivityPubActivityInterface $activity */
$activity = $storage->load(2);
self::assertEquals($actor_href, $activity->getActor());
self::assertEquals(ActivityPubActivityInterface::INBOX, $activity->getCollection());
self::assertEquals('Create', $activity->getType());
self::assertEquals($this->authenticatedUserTwo->id(), $activity->getOwnerId());
self::assertEquals($node->toUrl('canonical', ['absolute' => TRUE])->toString(), $activity->getObject());
$json = json_decode($activity->getPayLoad(), TRUE);
self::assertEquals('Note', $json['object']['type']);
self::assertEquals($json['id'], $activity->getExternalId());
self::assertEquals($node->toUrl('canonical', ['absolute' => TRUE])->toString(), $json['object']['id']);
self::assertEquals('<p>' . $node->get('body')->value . '</p>', $json['object']['content']);
}
/**
* Tests delete requests.
*/
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment