Skip to content

Commit b0ce41a

Browse files
WebvoidJPO-Klanikdebouncede-five256
authored
feat: implement private mode (#678)
Co-authored-by: Julien PONTILLO <jpontillo@klanik.com> Co-authored-by: debounced <35878315+nobodyatroot@users.noreply.github.com> Co-authored-by: e-five <146029455+e-five256@users.noreply.github.com>
1 parent 6694f84 commit b0ce41a

File tree

14 files changed

+115
-8
lines changed

14 files changed

+115
-8
lines changed

config/packages/security.yaml

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,55 @@ security:
6060
# This makes the logout route accessible during two-factor authentication. Allows the user to
6161
# cancel two-factor authentication, if they need to.
6262
- { path: ^/logout, role: PUBLIC_ACCESS }
63+
# This makes the login form and oauth routes accessible even when private instance is enabled
64+
- { path: ^/register, role: PUBLIC_ACCESS }
65+
- { path: ^/verify/email, role: PUBLIC_ACCESS }
66+
- { path: ^/reset-password, role: PUBLIC_ACCESS }
67+
- { path: ^/login, role: PUBLIC_ACCESS }
68+
- { path: ^/resend-email-activation, role: PUBLIC_ACCESS }
69+
- { path: ^/consent, role: PUBLIC_ACCESS }
70+
- { path: ^/oauth, role: PUBLIC_ACCESS }
71+
- { path: ^/terms, role: PUBLIC_ACCESS }
72+
- { path: ^/privacy-policy, role: PUBLIC_ACCESS }
73+
# Allow ActivityPub routes to work publicly
74+
- { attributes: { '_route': 'ap_webfinger' }, role: PUBLIC_ACCESS }
75+
- { attributes: { '_route': 'ap_hostmeta' }, role: PUBLIC_ACCESS }
76+
- { attributes: { '_route': 'ap_node_info' }, role: PUBLIC_ACCESS }
77+
- { attributes: { '_route': 'ap_node_info_v2' }, role: PUBLIC_ACCESS }
78+
- { attributes: { '_route': 'ap_instance' }, role: PUBLIC_ACCESS }
79+
- { attributes: { '_route': 'ap_instance_front' }, role: PUBLIC_ACCESS }
80+
- { attributes: { '_route': 'ap_instance_inbox' }, role: PUBLIC_ACCESS }
81+
- {
82+
attributes: { '_route': 'ap_instance_outbox' },
83+
role: PUBLIC_ACCESS,
84+
}
85+
- { attributes: { '_route': 'ap_shared_inbox' }, role: PUBLIC_ACCESS }
86+
- { attributes: { '_route': 'ap_object' }, role: PUBLIC_ACCESS }
87+
- { attributes: { '_route': 'ap_user' }, role: PUBLIC_ACCESS }
88+
- { attributes: { '_route': 'ap_user_inbox' }, role: PUBLIC_ACCESS }
89+
- { attributes: { '_route': 'ap_user_outbox' }, role: PUBLIC_ACCESS }
90+
- { attributes: { '_route': 'ap_user_followers' }, role: PUBLIC_ACCESS }
91+
- { attributes: { '_route': 'ap_user_following' }, role: PUBLIC_ACCESS }
92+
- { attributes: { '_route': 'ap_magazine' }, role: PUBLIC_ACCESS }
93+
- { attributes: { '_route': 'ap_magazine_inbox' }, role: PUBLIC_ACCESS }
94+
- {
95+
attributes: { '_route': 'ap_magazine_outbox' },
96+
role: PUBLIC_ACCESS,
97+
}
98+
- {
99+
attributes: { '_route': 'ap_magazine_followers' },
100+
role: PUBLIC_ACCESS,
101+
}
102+
- {
103+
attributes: { '_route': 'ap_magazine_moderators' },
104+
role: PUBLIC_ACCESS,
105+
}
106+
- { attributes: { '_route': 'ap_entry' }, role: PUBLIC_ACCESS }
107+
- { attributes: { '_route': 'ap_entry_comment' }, role: PUBLIC_ACCESS }
108+
- { attributes: { '_route': 'ap_post' }, role: PUBLIC_ACCESS }
109+
- { attributes: { '_route': 'ap_post_comment' }, role: PUBLIC_ACCESS }
110+
- { attributes: { '_route': 'ap_report' }, role: PUBLIC_ACCESS }
111+
- { attributes: { '_route': 'ap_contexts' }, role: PUBLIC_ACCESS }
63112
# allow custom style route access during two-factor authentication
64113
# to avoid redirecting (wrongly) to this route after two-factor authentication is completed
65114
- { path: ^/custom-style, role: PUBLIC_ACCESS }
@@ -71,6 +120,7 @@ security:
71120
- { path: ^/token, roles: PUBLIC_ACCESS }
72121
- { path: ^/api/doc, roles: PUBLIC_ACCESS }
73122
- { path: ^/api/client, roles: PUBLIC_ACCESS }
123+
- { path: ^/, roles: PUBLIC_ACCESS_UNLESS_PRIVATE_INSTANCE }
74124

75125
role_hierarchy:
76126
ROLE_OAUTH2_WRITE:

config/services.yaml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,6 @@ services:
190190
event: kernel.controller,
191191
priority: -5,
192192
}
193-
arguments: ["%kbin_federation_enabled%"]
194193

195194
App\EventListener\UserActivityListener:
196195
tags:

src/DTO/SettingsDto.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ public function __construct(
2929
public bool $KBIN_MERCURE_ENABLED,
3030
public bool $KBIN_FEDERATION_PAGE_ENABLED,
3131
public bool $KBIN_ADMIN_ONLY_OAUTH_CLIENTS,
32+
public bool $MBIN_PRIVATE_INSTANCE,
3233
public bool $KBIN_FEDERATED_SEARCH_ONLY_LOGGEDIN,
3334
public bool $MBIN_SIDEBAR_SECTIONS_LOCAL_ONLY,
3435
public bool $MBIN_SSO_REGISTRATIONS_ENABLED,
@@ -56,6 +57,7 @@ public function mergeIntoDto(SettingsDto $dto): SettingsDto
5657
$dto->KBIN_MERCURE_ENABLED = $this->KBIN_MERCURE_ENABLED ?? $dto->KBIN_MERCURE_ENABLED;
5758
$dto->KBIN_FEDERATION_PAGE_ENABLED = $this->KBIN_FEDERATION_PAGE_ENABLED ?? $dto->KBIN_FEDERATION_PAGE_ENABLED;
5859
$dto->KBIN_ADMIN_ONLY_OAUTH_CLIENTS = $this->KBIN_ADMIN_ONLY_OAUTH_CLIENTS ?? $dto->KBIN_ADMIN_ONLY_OAUTH_CLIENTS;
60+
$dto->MBIN_PRIVATE_INSTANCE = $this->MBIN_PRIVATE_INSTANCE ?? $dto->MBIN_PRIVATE_INSTANCE;
5961
$dto->KBIN_FEDERATED_SEARCH_ONLY_LOGGEDIN = $this->KBIN_FEDERATED_SEARCH_ONLY_LOGGEDIN ?? $dto->KBIN_FEDERATED_SEARCH_ONLY_LOGGEDIN;
6062
$dto->MBIN_SIDEBAR_SECTIONS_LOCAL_ONLY = $this->MBIN_SIDEBAR_SECTIONS_LOCAL_ONLY ?? $dto->MBIN_SIDEBAR_SECTIONS_LOCAL_ONLY;
6163
$dto->MBIN_SSO_REGISTRATIONS_ENABLED = $this->MBIN_SSO_REGISTRATIONS_ENABLED ?? $dto->MBIN_SSO_REGISTRATIONS_ENABLED;
@@ -85,6 +87,7 @@ public function jsonSerialize(): mixed
8587
'KBIN_MERCURE_ENABLED' => $this->KBIN_MERCURE_ENABLED,
8688
'KBIN_FEDERATION_PAGE_ENABLED' => $this->KBIN_FEDERATION_PAGE_ENABLED,
8789
'KBIN_ADMIN_ONLY_OAUTH_CLIENTS' => $this->KBIN_ADMIN_ONLY_OAUTH_CLIENTS,
90+
'MBIN_PRIVATE_INSTANCE' => $this->MBIN_PRIVATE_INSTANCE,
8891
'KBIN_FEDERATED_SEARCH_ONLY_LOGGEDIN' => $this->KBIN_FEDERATED_SEARCH_ONLY_LOGGEDIN,
8992
'MBIN_SIDEBAR_SECTIONS_LOCAL_ONLY' => $this->MBIN_SIDEBAR_SECTIONS_LOCAL_ONLY,
9093
'MBIN_SSO_REGISTRATIONS_ENABLED' => $this->MBIN_SSO_REGISTRATIONS_ENABLED,

src/EventListener/FederationStatusListener.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,19 @@
44

55
namespace App\EventListener;
66

7+
use App\Service\SettingsManager;
78
use Symfony\Component\HttpKernel\Event\ControllerEvent;
89
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
910

1011
class FederationStatusListener
1112
{
12-
public function __construct(private readonly bool $kbinFederationEnabled)
13+
public function __construct(private readonly SettingsManager $settingsManager)
1314
{
1415
}
1516

1617
public function onKernelController(ControllerEvent $event)
1718
{
18-
if (!$event->isMainRequest() || $this->kbinFederationEnabled) {
19+
if (!$event->isMainRequest() || $this->settingsManager->get('KBIN_FEDERATION_ENABLED')) {
1920
return;
2021
}
2122

src/Form/SettingsType.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ public function buildForm(FormBuilderInterface $builder, array $options): void
3636
->add('KBIN_MERCURE_ENABLED', CheckboxType::class, ['required' => false])
3737
->add('KBIN_FEDERATION_PAGE_ENABLED', CheckboxType::class, ['required' => false])
3838
->add('KBIN_ADMIN_ONLY_OAUTH_CLIENTS', CheckboxType::class, ['required' => false])
39+
->add('MBIN_PRIVATE_INSTANCE', CheckboxType::class, ['required' => false])
3940
->add('KBIN_FEDERATED_SEARCH_ONLY_LOGGEDIN', CheckboxType::class, ['required' => false])
4041
->add('MBIN_SIDEBAR_SECTIONS_LOCAL_ONLY', CheckboxType::class, ['required' => false])
4142
->add('MBIN_RESTRICT_MAGAZINE_CREATION', CheckboxType::class, ['required' => false])
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace App\Security\Voter;
6+
7+
use App\Entity\User;
8+
use App\Service\SettingsManager;
9+
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
10+
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
11+
12+
class PrivateInstanceVoter extends Voter
13+
{
14+
public function __construct(private SettingsManager $settingsManager)
15+
{
16+
}
17+
18+
protected function supports(string $attribute, $subject): bool
19+
{
20+
return 'PUBLIC_ACCESS_UNLESS_PRIVATE_INSTANCE' === $attribute;
21+
}
22+
23+
protected function voteOnAttribute(string $attribute, $subject, TokenInterface $token): bool
24+
{
25+
if ($this->settingsManager->get('MBIN_PRIVATE_INSTANCE')) {
26+
$user = $token->getUser();
27+
28+
if (!$user instanceof User) {
29+
return false;
30+
}
31+
}
32+
33+
return true;
34+
}
35+
}

src/Service/SettingsManager.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ public function __construct(
6464
$this->find($results, 'KBIN_MERCURE_ENABLED', FILTER_VALIDATE_BOOLEAN) ?? true,
6565
$this->find($results, 'KBIN_FEDERATION_PAGE_ENABLED', FILTER_VALIDATE_BOOLEAN) ?? $this->kbinFederationPageEnabled,
6666
$this->find($results, 'KBIN_ADMIN_ONLY_OAUTH_CLIENTS', FILTER_VALIDATE_BOOLEAN) ?? $this->kbinAdminOnlyOauthClients,
67+
$this->find($results, 'MBIN_PRIVATE_INSTANCE', FILTER_VALIDATE_BOOLEAN) ?? false,
6768
$this->find($results, 'KBIN_FEDERATED_SEARCH_ONLY_LOGGEDIN', FILTER_VALIDATE_BOOLEAN) ?? true,
6869
$this->find($results, 'MBIN_SIDEBAR_SECTIONS_LOCAL_ONLY', FILTER_VALIDATE_BOOLEAN) ?? false,
6970
$this->find($results, 'MBIN_SSO_REGISTRATIONS_ENABLED', FILTER_VALIDATE_BOOLEAN) ?? true,

src/Twig/Extension/SettingsExtension.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ public function getFunctions(): array
2828
new TwigFunction('kbin_federation_page_enabled', [SettingsExtensionRuntime::class, 'kbinFederationPageEnabled']),
2929
new TwigFunction('mbin_current_version', [SettingsExtensionRuntime::class, 'mbinCurrentVersion']),
3030
new TwigFunction('mbin_restrict_magazine_creation', [SettingsExtensionRuntime::class, 'mbinRestrictMagazineCreation']),
31+
new TwigFunction('mbin_private_instance', [SettingsExtensionRuntime::class, 'mbinPrivateInstance']),
3132
];
3233
}
3334
}

src/Twig/Runtime/SettingsExtensionRuntime.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,4 +103,9 @@ public function mbinRestrictMagazineCreation(): bool
103103
{
104104
return $this->settings->get('MBIN_RESTRICT_MAGAZINE_CREATION');
105105
}
106+
107+
public function mbinPrivateInstance(): bool
108+
{
109+
return $this->settings->get('MBIN_PRIVATE_INSTANCE');
110+
}
106111
}

templates/admin/settings.html.twig

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,10 @@
6363
{{ form_label(form.KBIN_ADMIN_ONLY_OAUTH_CLIENTS, 'restrict_oauth_clients') }}
6464
{{ form_widget(form.KBIN_ADMIN_ONLY_OAUTH_CLIENTS) }}
6565
</div>
66+
<div class="checkbox">
67+
{{ form_label(form.MBIN_PRIVATE_INSTANCE, 'private_instance') }}
68+
{{ form_widget(form.MBIN_PRIVATE_INSTANCE) }}
69+
</div>
6670
<div class="checkbox">
6771
{{ form_label(form.KBIN_FEDERATED_SEARCH_ONLY_LOGGEDIN, 'federated_search_only_loggedin') }}
6872
{{ form_widget(form.KBIN_FEDERATED_SEARCH_ONLY_LOGGEDIN) }}

0 commit comments

Comments
 (0)