[PLUGIN][UnboundGroup] Finish implementation
This commit is contained in:
parent
dfc5918c2c
commit
fd71d6ee7d
@ -91,7 +91,7 @@ class NoteToLink extends Entity
|
|||||||
$note = DB::find('note', ['id' => $args['note_id']]);
|
$note = DB::find('note', ['id' => $args['note_id']]);
|
||||||
Event::handle('NewLinkFromNote', [$link, $note]);
|
Event::handle('NewLinkFromNote', [$link, $note]);
|
||||||
$obj = new self();
|
$obj = new self();
|
||||||
return parent::createOrUpdate($args, $obj);
|
return parent::createOrUpdate(obj: $obj, args: $args);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function removeWhereNoteId(int $note_id): mixed
|
public static function removeWhereNoteId(int $note_id): mixed
|
||||||
|
@ -324,14 +324,20 @@ class ActivityPub extends Plugin
|
|||||||
): bool {
|
): bool {
|
||||||
try {
|
try {
|
||||||
$data = Model::toType($activity);
|
$data = Model::toType($activity);
|
||||||
if ($sender->isGroup() && ($activity->getVerb() !== 'subscribe' || !($activity->getVerb() === 'undo' && $data->get('object')->get('type') === 'Follow'))) {
|
if ($sender->isGroup()) { // When the sender is a group,
|
||||||
// When the sender is a group, we have to wrap it in a transient Announce activity
|
if ($activity->getVerb() === 'subscribe') {
|
||||||
|
// Regular postman happens
|
||||||
|
} elseif ($activity->getVerb() === 'undo' && $data->get('object')->get('type') === 'Follow') {
|
||||||
|
// Regular postman happens
|
||||||
|
} else {
|
||||||
|
// For every other activity sent by a Group, we have to wrap it in a transient Announce activity
|
||||||
$data = Type::create('Announce', [
|
$data = Type::create('Announce', [
|
||||||
'@context' => 'https:\/\/www.w3.org\/ns\/activitystreams',
|
'@context' => 'https:\/\/www.w3.org\/ns\/activitystreams',
|
||||||
'actor' => $sender->getUri(type: Router::ABSOLUTE_URL),
|
'actor' => $sender->getUri(type: Router::ABSOLUTE_URL),
|
||||||
'object' => $data,
|
'object' => $data,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
$res = self::postman($sender, $data->toJson(), $inbox);
|
$res = self::postman($sender, $data->toJson(), $inbox);
|
||||||
|
|
||||||
// accumulate errors for later use, if needed
|
// accumulate errors for later use, if needed
|
||||||
|
@ -198,6 +198,7 @@ class Actor extends Model
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Event::handle('ActivityPubCreateOrUpdateActor', [$object, &$actor, &$ap_actor]);
|
||||||
return $ap_actor;
|
return $ap_actor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@ declare(strict_types = 1);
|
|||||||
namespace Plugin\UnboundGroup\Controller;
|
namespace Plugin\UnboundGroup\Controller;
|
||||||
|
|
||||||
use App\Core\Controller;
|
use App\Core\Controller;
|
||||||
|
use App\Core\DB;
|
||||||
use App\Core\Form;
|
use App\Core\Form;
|
||||||
use function App\Core\I18n\_m;
|
use function App\Core\I18n\_m;
|
||||||
use App\Entity as E;
|
use App\Entity as E;
|
||||||
@ -12,12 +13,60 @@ use App\Util\Common;
|
|||||||
use App\Util\Exception\ClientException;
|
use App\Util\Exception\ClientException;
|
||||||
use Component\Subscription\Subscription;
|
use Component\Subscription\Subscription;
|
||||||
use Plugin\ActivityPub\Util\Explorer;
|
use Plugin\ActivityPub\Util\Explorer;
|
||||||
|
use Plugin\UnboundGroup\Entity\activitypubGroupUnbound;
|
||||||
|
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||||
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
|
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
|
||||||
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
||||||
use Symfony\Component\HttpFoundation\Request;
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
|
|
||||||
class GroupSettings extends Controller
|
class GroupSettings extends Controller
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Manage the gs:unbound state
|
||||||
|
*/
|
||||||
|
public static function groupUnbound(Request $request, E\Actor $target, string $details_id)
|
||||||
|
{
|
||||||
|
$actor = Common::ensureLoggedIn()->getActor();
|
||||||
|
if (!$actor->canModerate($target)) {
|
||||||
|
throw new ClientException(_m('You don\'t have enough permissions to edit {nickname}\'s settings', ['{nickname}' => $target->getNickname()]));
|
||||||
|
}
|
||||||
|
|
||||||
|
$unbound_options = [
|
||||||
|
_m('Default') => null,
|
||||||
|
_m('True') => true,
|
||||||
|
_m('False') => false,
|
||||||
|
];
|
||||||
|
|
||||||
|
$obj = DB::findOneBy(activitypubGroupUnbound::class, ['actor_id' => $target->getId()], return_null: true);
|
||||||
|
|
||||||
|
$form_definition = [
|
||||||
|
['new_state', ChoiceType::class, ['label' => _m('Unbound:'), 'multiple' => false, 'expanded' => false, 'choices' => $unbound_options, 'data' => $obj?->getUnbound()]],
|
||||||
|
[$save_unbound_state_form_name = 'save_group_links', SubmitType::class, ['label' => _m('Save state')]],
|
||||||
|
];
|
||||||
|
|
||||||
|
$unbound_state_form = Form::create($form_definition);
|
||||||
|
|
||||||
|
if ($request->getMethod() === 'POST' && $request->request->has($save_unbound_state_form_name)) {
|
||||||
|
$unbound_state_form->handleRequest($request);
|
||||||
|
if ($unbound_state_form->isSubmitted() && $unbound_state_form->isValid()) {
|
||||||
|
$new_state = $unbound_state_form->getData()['new_state'];
|
||||||
|
$update_obj = activitypubGroupUnbound::createOrUpdate(obj: $obj, args: [
|
||||||
|
'actor_id' => $target->getId(),
|
||||||
|
'unbound' => $new_state,
|
||||||
|
]);
|
||||||
|
if (\is_null($obj)) {
|
||||||
|
DB::persist($update_obj);
|
||||||
|
}
|
||||||
|
DB::flush();
|
||||||
|
Form::forceRedirect($unbound_state_form, $request);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
'_template' => 'self_tags_settings.fragment.html.twig',
|
||||||
|
'add_self_tags_form' => $unbound_state_form->createView(),
|
||||||
|
];
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Manage the linksTo collection of a Group or Organisation Actor
|
* Manage the linksTo collection of a Group or Organisation Actor
|
||||||
*/
|
*/
|
||||||
@ -40,10 +89,14 @@ class GroupSettings extends Controller
|
|||||||
if ($add_link_to_form->isSubmitted() && $add_link_to_form->isValid()) {
|
if ($add_link_to_form->isSubmitted() && $add_link_to_form->isValid()) {
|
||||||
if (Common::isValidHttpUrl($new_uri = $add_link_to_form->getData()['new_link'])) {
|
if (Common::isValidHttpUrl($new_uri = $add_link_to_form->getData()['new_link'])) {
|
||||||
$new_link = Explorer::getOneFromUri($new_uri);
|
$new_link = Explorer::getOneFromUri($new_uri);
|
||||||
|
|
||||||
|
$unbound = DB::findOneBy(activitypubGroupUnbound::class, ['actor_id' => $new_link->getId()], return_null: true);
|
||||||
|
if ($unbound?->getUnbound() ?? true) {
|
||||||
if (\is_null(Subscription::subscribe(subject: $target, object: $new_link, source: 'ActivityPub via FEP-2100'))) {
|
if (\is_null(Subscription::subscribe(subject: $target, object: $new_link, source: 'ActivityPub via FEP-2100'))) {
|
||||||
throw new ClientException(_m('This group is already linked from {nickname}', ['{nickname}' => $new_link->getNickname()]));
|
throw new ClientException(_m('This group is already linked from {nickname}', ['{nickname}' => $new_link->getNickname()]));
|
||||||
}
|
}
|
||||||
Subscription::refreshSubscriptionCount($target, $new_link);
|
Subscription::refreshSubscriptionCount($target, $new_link);
|
||||||
|
}
|
||||||
Form::forceRedirect($add_link_to_form, $request);
|
Form::forceRedirect($add_link_to_form, $request);
|
||||||
} else {
|
} else {
|
||||||
throw new ClientException(_m('Invalid URI given.'));
|
throw new ClientException(_m('Invalid URI given.'));
|
||||||
|
53
plugins/UnboundGroup/Entity/activitypubGroupUnbound.php
Normal file
53
plugins/UnboundGroup/Entity/activitypubGroupUnbound.php
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types = 1);
|
||||||
|
|
||||||
|
namespace Plugin\UnboundGroup\Entity;
|
||||||
|
|
||||||
|
use App\Core\Entity;
|
||||||
|
|
||||||
|
class activitypubGroupUnbound extends Entity
|
||||||
|
{
|
||||||
|
// These tags are meant to be literally included and will be populated with the appropriate fields, setters and getters by `bin/generate_entity_fields`
|
||||||
|
// {{{ Autocode
|
||||||
|
// @codeCoverageIgnoreStart
|
||||||
|
private int $actor_id;
|
||||||
|
private ?bool $unbound = null;
|
||||||
|
|
||||||
|
public function setActorId(int $actor_id): self
|
||||||
|
{
|
||||||
|
$this->actor_id = $actor_id;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getActorId(): int
|
||||||
|
{
|
||||||
|
return $this->actor_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setUnbound(?bool $unbound): self
|
||||||
|
{
|
||||||
|
$this->unbound = $unbound;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getUnbound(): ?bool
|
||||||
|
{
|
||||||
|
return $this->unbound;
|
||||||
|
}
|
||||||
|
|
||||||
|
// @codeCoverageIgnoreEnd
|
||||||
|
// }}} Autocode
|
||||||
|
|
||||||
|
public static function schemaDef(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'name' => 'activitypubGroupUnbound',
|
||||||
|
'fields' => [
|
||||||
|
'actor_id' => ['type' => 'int', 'foreign key' => true, 'target' => 'Actor.id', 'multiplicity' => 'one to one', 'not null' => true, 'description' => 'foreign key to actor table'],
|
||||||
|
'unbound' => ['type' => 'bool', 'not null' => false, 'description' => 'gs:unbound'],
|
||||||
|
],
|
||||||
|
'primary key' => ['actor_id'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
@ -32,10 +32,13 @@ declare(strict_types = 1);
|
|||||||
|
|
||||||
namespace Plugin\UnboundGroup;
|
namespace Plugin\UnboundGroup;
|
||||||
|
|
||||||
|
use App\Core\DB;
|
||||||
use App\Core\Event;
|
use App\Core\Event;
|
||||||
use App\Core\Modules\Plugin;
|
use App\Core\Modules\Plugin;
|
||||||
use App\Entity\Actor;
|
use App\Entity\Actor;
|
||||||
|
use Plugin\ActivityPub\Entity\ActivitypubActor;
|
||||||
use Plugin\UnboundGroup\Controller\GroupSettings;
|
use Plugin\UnboundGroup\Controller\GroupSettings;
|
||||||
|
use Plugin\UnboundGroup\Entity\activitypubGroupUnbound;
|
||||||
use Symfony\Component\HttpFoundation\Request;
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -49,6 +52,12 @@ class UnboundGroup extends Plugin
|
|||||||
public function onPopulateSettingsTabs(Request $request, string $section, array &$tabs): bool
|
public function onPopulateSettingsTabs(Request $request, string $section, array &$tabs): bool
|
||||||
{
|
{
|
||||||
if ($section === 'profile' && $request->get('_route') === 'group_actor_settings') {
|
if ($section === 'profile' && $request->get('_route') === 'group_actor_settings') {
|
||||||
|
$tabs[] = [
|
||||||
|
'title' => 'Unbound',
|
||||||
|
'desc' => 'Unbound Group state.',
|
||||||
|
'id' => 'settings-group-unbound-details',
|
||||||
|
'controller' => GroupSettings::groupUnbound($request, Actor::getById((int) $request->get('id')), 'settings-group-unbound-details'),
|
||||||
|
];
|
||||||
$tabs[] = [
|
$tabs[] = [
|
||||||
'title' => 'Linked',
|
'title' => 'Linked',
|
||||||
'desc' => 'Link to this Group from another Group.',
|
'desc' => 'Link to this Group from another Group.',
|
||||||
@ -58,4 +67,41 @@ class UnboundGroup extends Plugin
|
|||||||
}
|
}
|
||||||
return Event::next;
|
return Event::next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function onActivityStreamsTwoContext(array &$activity_streams_two_context): bool
|
||||||
|
{
|
||||||
|
$activity_streams_two_context[] = [
|
||||||
|
'unbound' => [
|
||||||
|
'@id' => 'gs:unbound',
|
||||||
|
'@type' => '@id',
|
||||||
|
],
|
||||||
|
];
|
||||||
|
return Event::next;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function onActivityPubAddActivityStreamsTwoData(string $type_name, &$type): bool
|
||||||
|
{
|
||||||
|
if ($type_name === 'Group' || $type_name === 'Organization') {
|
||||||
|
$actor = \Plugin\ActivityPub\Util\Explorer::getOneFromUri($type->getId());
|
||||||
|
$unbound = DB::findOneBy(activitypubGroupUnbound::class, ['actor_id' => $actor->getId()], return_null: true);
|
||||||
|
|
||||||
|
if (!\is_null($unbound_value = $unbound?->getUnbound())) {
|
||||||
|
$type->set('unbound', $unbound_value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Event::next;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function onActivityPubCreateOrUpdateActor(\ActivityPhp\Type\AbstractObject $object, Actor $actor, ActivitypubActor $ap_actor): bool
|
||||||
|
{
|
||||||
|
if ($object->has('unbound')) {
|
||||||
|
$obj = DB::findOneBy(activitypubGroupUnbound::class, ['actor_id' => $actor->getId()], return_null: true);
|
||||||
|
$update_obj = activitypubGroupUnbound::createOrUpdate(obj: $obj, args: ['actor_id' => $actor->getId(), 'unbound' => $object->get('unbound')]);
|
||||||
|
if (\is_null($obj)) {
|
||||||
|
DB::persist($update_obj);
|
||||||
|
}
|
||||||
|
DB::flush();
|
||||||
|
}
|
||||||
|
return Event::next;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -43,6 +43,7 @@ use App\Entity\LocalUser;
|
|||||||
use App\Util\Common;
|
use App\Util\Common;
|
||||||
use App\Util\Exception\RedirectException;
|
use App\Util\Exception\RedirectException;
|
||||||
use App\Util\Formatting;
|
use App\Util\Formatting;
|
||||||
|
use Plugin\ActivityPub\Entity\ActivitypubActor;
|
||||||
use Plugin\WebMonetization\Entity\Wallet;
|
use Plugin\WebMonetization\Entity\Wallet;
|
||||||
use Plugin\WebMonetization\Entity\WebMonetization as Monetization;
|
use Plugin\WebMonetization\Entity\WebMonetization as Monetization;
|
||||||
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
|
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
|
||||||
@ -263,4 +264,14 @@ class WebMonetization extends Plugin
|
|||||||
}
|
}
|
||||||
return Event::next;
|
return Event::next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function onActivityPubCreateOrUpdateActor(\ActivityPhp\Type\AbstractObject $object, Actor $actor, ActivitypubActor $ap_actor): bool
|
||||||
|
{
|
||||||
|
if ($object->has('webmonetizationWallet')) {
|
||||||
|
$attr = ['actor_id' => $actor->getId(), 'address' => $object->get('webmonetizationWallet')];
|
||||||
|
$obj = DB::findOneBy(Wallet::class, $attr, return_null: true);
|
||||||
|
DB::persist(Wallet::createOrUpdate(obj: $obj, args: $attr));
|
||||||
|
}
|
||||||
|
return Event::next;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user