File tree Expand file tree Collapse file tree
lib/private/DirectEditing Expand file tree Collapse file tree Original file line number Diff line number Diff line change 3838use OC \Core \Sharing \Recipient \TeamShareRecipientType ;
3939use OC \Core \Sharing \Recipient \TokenShareRecipientType ;
4040use OC \Core \Sharing \Recipient \UserShareRecipientType ;
41+ use OC \DirectEditing \Listeners \UserDeletedTokenCleanupListener as UserDeletedDirectEditingTokenCleanupListener ;
42+ use OC \DirectEditing \Listeners \UserDisabledTokenCleanupListener as UserDisabledDirectEditingTokenCleanupListener ;
4143use OC \OCM \OCMDiscoveryHandler ;
4244use OC \OCM \OCMJwksHandler ;
4345use OC \TagManager ;
5557use OCP \Server ;
5658use OCP \User \Events \BeforeUserDeletedEvent ;
5759use OCP \User \Events \PasswordUpdatedEvent ;
60+ use OCP \User \Events \UserChangedEvent ;
5861use OCP \User \Events \UserDeletedEvent ;
5962use OCP \Util ;
6063
@@ -115,6 +118,10 @@ public function register(IRegistrationContext $context): void {
115118
116119 $ context ->registerEventListener (RestrictInteractionEvent::class, RestrictInteractionListener::class);
117120
121+ // Direct Editing
122+ $ context ->registerEventListener (UserDeletedEvent::class, UserDeletedDirectEditingTokenCleanupListener::class);
123+ $ context ->registerEventListener (UserChangedEvent::class, UserDisabledDirectEditingTokenCleanupListener::class);
124+
118125 $ registry = Server::get (ISharingRegistry::class);
119126
120127 $ registry ->registerRecipientType (Server::get (EmailShareRecipientType::class));
Original file line number Diff line number Diff line change 1+ <?php
2+
3+ declare (strict_types=1 );
4+
5+ /**
6+ * SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
7+ * SPDX-License-Identifier: AGPL-3.0-or-later
8+ */
9+
10+ namespace OC \DirectEditing \Listeners ;
11+
12+ use OC \DirectEditing \Manager ;
13+ use OCP \EventDispatcher \Event ;
14+ use OCP \EventDispatcher \IEventListener ;
15+ use OCP \User \Events \UserDeletedEvent ;
16+ use Psr \Log \LoggerInterface ;
17+ use Throwable ;
18+
19+ /**
20+ * @template-implements IEventListener<UserDeletedEvent>
21+ */
22+ class UserDeletedTokenCleanupListener implements IEventListener {
23+ public function __construct (
24+ private Manager $ manager ,
25+ private LoggerInterface $ logger ,
26+ ) {
27+ }
28+
29+ #[\Override]
30+ public function handle (Event $ event ): void {
31+ if (!($ event instanceof UserDeletedEvent)) {
32+ // Unrelated
33+ return ;
34+ }
35+
36+ /**
37+ * Catch any exception during this process as any failure here shouldn't block the
38+ * user deletion.
39+ */
40+ try {
41+ $ uid = $ event ->getUser ()->getUID ();
42+ $ this ->manager ->invalidateTokensForUser ($ uid );
43+ } catch (Throwable $ e ) {
44+ $ this ->logger ->error ('Could not clean up direct editing tokens after user deletion: ' . $ e ->getMessage (), [
45+ 'exception ' => $ e ,
46+ ]);
47+ }
48+ }
49+ }
Original file line number Diff line number Diff line change 1+ <?php
2+
3+ declare (strict_types=1 );
4+
5+ /**
6+ * SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
7+ * SPDX-License-Identifier: AGPL-3.0-or-later
8+ */
9+
10+ namespace OC \DirectEditing \Listeners ;
11+
12+ use OC \DirectEditing \Manager ;
13+ use OCP \EventDispatcher \Event ;
14+ use OCP \EventDispatcher \IEventListener ;
15+ use OCP \User \Events \UserChangedEvent ;
16+ use Psr \Log \LoggerInterface ;
17+ use Throwable ;
18+
19+ /**
20+ * @template-implements IEventListener<UserChangedEvent>
21+ */
22+ class UserDisabledTokenCleanupListener implements IEventListener {
23+ public function __construct (
24+ private Manager $ manager ,
25+ private LoggerInterface $ logger ,
26+ ) {
27+ }
28+
29+ #[\Override]
30+ public function handle (Event $ event ): void {
31+ if (!($ event instanceof UserChangedEvent)) {
32+ // Unrelated
33+ return ;
34+ }
35+
36+ if ($ event ->getFeature () !== 'enabled ' || $ event ->getValue ()) {
37+ // not disabled
38+ return ;
39+ }
40+
41+ /**
42+ * Catch any exception during this process
43+ * as any failure here shouldn't block the disabling the user.
44+ */
45+ try {
46+ $ uid = $ event ->getUser ()->getUID ();
47+ $ this ->manager ->invalidateTokensForUser ($ uid );
48+ } catch (Throwable $ e ) {
49+ $ this ->logger ->error ('Could not clean up direct editing tokens when disabling user: ' . $ e ->getMessage (), [
50+ 'exception ' => $ e ,
51+ ]);
52+ }
53+ }
54+ }
Original file line number Diff line number Diff line change @@ -218,6 +218,13 @@ public function cleanup(): int {
218218 return $ query ->executeStatement ();
219219 }
220220
221+ public function invalidateTokensForUser (string $ uid ): int {
222+ $ query = $ this ->connection ->getQueryBuilder ();
223+ $ query ->delete (self ::TABLE_TOKENS )
224+ ->where ($ query ->expr ()->eq ('user_id ' , $ query ->createNamedParameter ($ uid )));
225+ return $ query ->executeStatement ();
226+ }
227+
221228 public function refreshToken (string $ token ): bool {
222229 $ query = $ this ->connection ->getQueryBuilder ();
223230 $ query ->update (self ::TABLE_TOKENS )
You can’t perform that action at this time.
0 commit comments