forked from GNUsocial/gnu-social
[COMPONENT][GROUP] Allow to create a group as private and prioritise group scope on Posting in that context
This commit is contained in:
parent
090a087832
commit
bc63c3727a
@ -208,6 +208,10 @@ class Group extends FeedController
|
|||||||
_m('Group') => 'group',
|
_m('Group') => 'group',
|
||||||
_m('Organisation') => 'organisation',
|
_m('Organisation') => 'organisation',
|
||||||
]]],
|
]]],
|
||||||
|
['group_scope', ChoiceType::class, ['label' => _m('Is this a private group:'), 'multiple' => false, 'expanded' => false, 'choices' => [
|
||||||
|
_m('No') => 'public',
|
||||||
|
_m('Yes') => 'private',
|
||||||
|
]]],
|
||||||
['group_create', SubmitType::class, ['label' => _m('Create this group!')]],
|
['group_create', SubmitType::class, ['label' => _m('Create this group!')]],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
@ -221,9 +225,15 @@ class Group extends FeedController
|
|||||||
check_is_allowed: true
|
check_is_allowed: true
|
||||||
);
|
);
|
||||||
|
|
||||||
|
$roles = ActorLocalRoles::VISITOR; // Can send direct messages to other actors
|
||||||
|
|
||||||
|
if ($data['group_scope'] === 'private') {
|
||||||
|
$roles |= ActorLocalRoles::PRIVATE_GROUP;
|
||||||
|
}
|
||||||
|
|
||||||
Log::info(
|
Log::info(
|
||||||
_m(
|
_m(
|
||||||
'Actor id:{actor_id} nick:{actor_nick} created the group {nickname}',
|
'Actor id:{actor_id} nick:{actor_nick} created the '.($roles & ActorLocalRoles::PRIVATE_GROUP ? 'private' : 'public').' group {nickname}',
|
||||||
['{actor_id}' => $actor->getId(), 'actor_nick' => $actor->getNickname(), 'nickname' => $nickname],
|
['{actor_id}' => $actor->getId(), 'actor_nick' => $actor->getNickname(), 'nickname' => $nickname],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@ -232,7 +242,7 @@ class Group extends FeedController
|
|||||||
'nickname' => $nickname,
|
'nickname' => $nickname,
|
||||||
'type' => E\Actor::GROUP,
|
'type' => E\Actor::GROUP,
|
||||||
'is_local' => true,
|
'is_local' => true,
|
||||||
'roles' => ActorLocalRoles::VISITOR, // Can send direct messages to other actors
|
'roles' => $roles,
|
||||||
]));
|
]));
|
||||||
DB::persist(LocalGroup::create([
|
DB::persist(LocalGroup::create([
|
||||||
'actor_id' => $group->getId(),
|
'actor_id' => $group->getId(),
|
||||||
|
@ -23,6 +23,7 @@ declare(strict_types = 1);
|
|||||||
|
|
||||||
namespace Component\Posting;
|
namespace Component\Posting;
|
||||||
|
|
||||||
|
use App\Core\ActorLocalRoles;
|
||||||
use App\Core\DB\DB;
|
use App\Core\DB\DB;
|
||||||
use App\Core\Event;
|
use App\Core\Event;
|
||||||
use App\Core\Form;
|
use App\Core\Form;
|
||||||
@ -119,9 +120,15 @@ class Posting extends Component
|
|||||||
_m('Addressee') => VisibilityScope::ADDRESSEE->value,
|
_m('Addressee') => VisibilityScope::ADDRESSEE->value,
|
||||||
];
|
];
|
||||||
if (!is_null($context_actor) && $context_actor->isGroup()) {
|
if (!is_null($context_actor) && $context_actor->isGroup()) {
|
||||||
$visibility_options[_m('Group')] = VisibilityScope::GROUP->value;
|
if ($actor->canAdmin($context_actor)) {
|
||||||
|
if ($context_actor->getRoles() & ActorLocalRoles::PRIVATE_GROUP) {
|
||||||
|
$visibility_options = array_merge([_m('Group') => VisibilityScope::GROUP->value], $visibility_options);
|
||||||
|
} else {
|
||||||
|
$visibility_options[_m('Group')] = VisibilityScope::GROUP->value;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
$form_params[] = ['visibility', ChoiceType::class, ['label' => _m('Visibility:'), 'multiple' => false, 'expanded' => false, 'data' => 'public', 'choices' => $visibility_options]];
|
$form_params[] = ['visibility', ChoiceType::class, ['label' => _m('Visibility:'), 'multiple' => false, 'expanded' => false, 'choices' => $visibility_options]];
|
||||||
|
|
||||||
$form_params[] = ['content', TextareaType::class, ['label' => _m('Content:'), 'data' => $initial_content, 'attr' => ['placeholder' => _m($placeholder)], 'constraints' => [new Length(['max' => Common::config('site', 'text_limit')])]]];
|
$form_params[] = ['content', TextareaType::class, ['label' => _m('Content:'), 'data' => $initial_content, 'attr' => ['placeholder' => _m($placeholder)], 'constraints' => [new Length(['max' => Common::config('site', 'text_limit')])]]];
|
||||||
$form_params[] = ['attachments', FileType::class, ['label' => _m('Attachments:'), 'multiple' => true, 'required' => false, 'invalid_message' => _m('Attachment not valid.')]];
|
$form_params[] = ['attachments', FileType::class, ['label' => _m('Attachments:'), 'multiple' => true, 'required' => false, 'invalid_message' => _m('Attachment not valid.')]];
|
||||||
|
@ -83,18 +83,35 @@ class Actor extends Model
|
|||||||
*/
|
*/
|
||||||
public static function fromJson(string|AbstractObject $json, array $options = []): ActivitypubActor
|
public static function fromJson(string|AbstractObject $json, array $options = []): ActivitypubActor
|
||||||
{
|
{
|
||||||
$person = \is_string($json) ? self::jsonToType($json) : $json;
|
$object = \is_string($json) ? self::jsonToType($json) : $json;
|
||||||
|
|
||||||
|
switch ($object->get('type')) {
|
||||||
|
case 'Application':
|
||||||
|
case 'Person':
|
||||||
|
// TODO: Operator may prefer users to start with Visitor and then have them being manually promoted
|
||||||
|
$roles = ActorLocalRoles::PARTICIPANT | ActorLocalRoles::VISITOR; // Can view and participate
|
||||||
|
break;
|
||||||
|
case 'Group':
|
||||||
|
case 'Organisation':
|
||||||
|
$roles = ActorLocalRoles::VISITOR; // Can send direct messages to other actors
|
||||||
|
if ($object->get('private')) {
|
||||||
|
$roles |= ActorLocalRoles::PRIVATE_GROUP;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'Service':
|
||||||
|
default:
|
||||||
|
$roles = ActorLocalRoles::NONE;
|
||||||
|
}
|
||||||
|
|
||||||
// Actor
|
// Actor
|
||||||
$actor_map = [
|
$actor_map = [
|
||||||
'nickname' => $person->get('preferredUsername'),
|
'nickname' => $object->get('preferredUsername'),
|
||||||
'fullname' => !empty($person->get('name')) ? $person->get('name') : null,
|
'fullname' => !empty($object->get('name')) ? $object->get('name') : null,
|
||||||
'created' => new DateTime($person->get('published') ?? 'now'),
|
'created' => new DateTime($object->get('published') ?? 'now'),
|
||||||
'bio' => $person->get('summary'),
|
'bio' => $object->get('summary'),
|
||||||
'is_local' => false, // duh!
|
'is_local' => false, // duh!
|
||||||
'type' => self::$_as2_actor_type_to_gs_actor_type[$person->get('type')],
|
'type' => self::$_as2_actor_type_to_gs_actor_type[$object->get('type')],
|
||||||
// TODO: Operator may prefer users to start with Visitor and then have them being manually promoted
|
'roles' => $roles,
|
||||||
'roles' => ActorLocalRoles::PARTICIPANT | ActorLocalRoles::VISITOR, // Can view and participate
|
|
||||||
'modified' => new DateTime(),
|
'modified' => new DateTime(),
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -111,11 +128,11 @@ class Actor extends Model
|
|||||||
|
|
||||||
// ActivityPub Actor
|
// ActivityPub Actor
|
||||||
$ap_actor = ActivitypubActor::create([
|
$ap_actor = ActivitypubActor::create([
|
||||||
'inbox_uri' => $person->get('inbox'),
|
'inbox_uri' => $object->get('inbox'),
|
||||||
'inbox_shared_uri' => ($person->has('endpoints') && isset($person->get('endpoints')['sharedInbox'])) ? $person->get('endpoints')['sharedInbox'] : null,
|
'inbox_shared_uri' => ($object->has('endpoints') && isset($object->get('endpoints')['sharedInbox'])) ? $object->get('endpoints')['sharedInbox'] : null,
|
||||||
'uri' => $person->get('id'),
|
'uri' => $object->get('id'),
|
||||||
'actor_id' => $actor->getId(),
|
'actor_id' => $actor->getId(),
|
||||||
'url' => $person->get('url') ?? null,
|
'url' => $object->get('url') ?? null,
|
||||||
], $options['objects']['ActivitypubActor'] ?? null);
|
], $options['objects']['ActivitypubActor'] ?? null);
|
||||||
|
|
||||||
if (!isset($options['objects']['ActivitypubActor'])) {
|
if (!isset($options['objects']['ActivitypubActor'])) {
|
||||||
@ -125,7 +142,7 @@ class Actor extends Model
|
|||||||
// Public Key
|
// Public Key
|
||||||
$apRSA = ActivitypubRsa::create([
|
$apRSA = ActivitypubRsa::create([
|
||||||
'actor_id' => $actor->getID(),
|
'actor_id' => $actor->getID(),
|
||||||
'public_key' => ($person->has('publicKey') && isset($person->get('publicKey')['publicKeyPem'])) ? $person->get('publicKey')['publicKeyPem'] : null,
|
'public_key' => ($object->has('publicKey') && isset($object->get('publicKey')['publicKeyPem'])) ? $object->get('publicKey')['publicKeyPem'] : null,
|
||||||
], $options['objects']['ActivitypubRsa'] ?? null);
|
], $options['objects']['ActivitypubRsa'] ?? null);
|
||||||
|
|
||||||
if (!isset($options['objects']['ActivitypubRsa'])) {
|
if (!isset($options['objects']['ActivitypubRsa'])) {
|
||||||
@ -133,10 +150,10 @@ class Actor extends Model
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Avatar
|
// Avatar
|
||||||
if ($person->has('icon') && !empty($person->get('icon'))) {
|
if ($object->has('icon') && !empty($object->get('icon'))) {
|
||||||
try {
|
try {
|
||||||
// Retrieve media
|
// Retrieve media
|
||||||
$get_response = HTTPClient::get($person->get('icon')->get('url'));
|
$get_response = HTTPClient::get($object->get('icon')->get('url'));
|
||||||
$media = $get_response->getContent();
|
$media = $get_response->getContent();
|
||||||
$mimetype = $get_response->getHeaders()['content-type'][0] ?? null;
|
$mimetype = $get_response->getHeaders()['content-type'][0] ?? null;
|
||||||
unset($get_response);
|
unset($get_response);
|
||||||
@ -153,12 +170,12 @@ class Actor extends Model
|
|||||||
if (!\is_null($avatar = DB::findOneBy(\Component\Avatar\Entity\Avatar::class, ['actor_id' => $actor->getId()], return_null: true))) {
|
if (!\is_null($avatar = DB::findOneBy(\Component\Avatar\Entity\Avatar::class, ['actor_id' => $actor->getId()], return_null: true))) {
|
||||||
$avatar->delete();
|
$avatar->delete();
|
||||||
}
|
}
|
||||||
DB::wrapInTransaction(function () use ($attachment, $actor, $person) {
|
DB::wrapInTransaction(function () use ($attachment, $actor, $object) {
|
||||||
DB::persist($attachment);
|
DB::persist($attachment);
|
||||||
DB::persist(\Component\Avatar\Entity\Avatar::create([
|
DB::persist(\Component\Avatar\Entity\Avatar::create([
|
||||||
'actor_id' => $actor->getId(),
|
'actor_id' => $actor->getId(),
|
||||||
'attachment_id' => $attachment->getId(),
|
'attachment_id' => $attachment->getId(),
|
||||||
'title' => $person->get('icon')->get('name') ?? null,
|
'title' => $object->get('icon')->get('name') ?? null,
|
||||||
]));
|
]));
|
||||||
});
|
});
|
||||||
Event::handle('AvatarUpdate', [$actor->getId()]);
|
Event::handle('AvatarUpdate', [$actor->getId()]);
|
||||||
@ -255,6 +272,12 @@ class Actor extends Model
|
|||||||
// No icon for this actor
|
// No icon for this actor
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($object->isGroup()) {
|
||||||
|
if ($object->getRoles() & ActorLocalRoles::PRIVATE_GROUP) {
|
||||||
|
$attr['private'] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$type = self::jsonToType($attr);
|
$type = self::jsonToType($attr);
|
||||||
Event::handle('ActivityPubAddActivityStreamsTwoData', [$type->get('type'), &$type]);
|
Event::handle('ActivityPubAddActivityStreamsTwoData', [$type->get('type'), &$type]);
|
||||||
return $type->toJson($options);
|
return $type->toJson($options);
|
||||||
|
Loading…
Reference in New Issue
Block a user