Skip to content

Commit 7f66a22

Browse files
Aiiaiiiomiaulalala
authored andcommitted
feat: adding an option to exclude users from the acitivity log
Signed-off-by: Tamás Bari <adaorcpp@gmail.com> fix: Fixing missing $affectedUser in storeMail() Signed-off-by: Tamás Bari <adaorcpp@gmail.com> fix: Removing 'all' as an even type filter option for excluded users Signed-off-by: Tamás Bari <adaorcpp@gmail.com> chore: Adding tests for excluded users Signed-off-by: Tamás Bari <adaorcpp@gmail.com> fix: Removing dead code from condition Signed-off-by: Tamás Bari <adaorcpp@gmail.com> fix: logging an error when activity_log_exclude_users looks invalid Signed-off-by: Tamás Bari <adaorcpp@gmail.com> fix: Fixing indentation Signed-off-by: Tamás Bari <adaorcpp@gmail.com>
1 parent 426a4bf commit 7f66a22

2 files changed

Lines changed: 167 additions & 4 deletions

File tree

lib/Data.php

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,14 +38,51 @@ public function __construct(
3838
) {
3939
}
4040

41+
/**
42+
* Check if the event should be processed (not excluded and has valid target)
43+
*
44+
* @param IEvent $event
45+
* @return bool
46+
*/
47+
private function shouldSend(IEvent $event): bool {
48+
return $event->getAffectedUser() !== '' && !$this->isExcludedAuthor($event);
49+
}
50+
51+
/**
52+
* Check if the event's author is excluded from activity logging
53+
*
54+
* @param IEvent $event
55+
* @return bool
56+
*/
57+
private function isExcludedAuthor(IEvent $event): bool {
58+
$excludedUsers = $this->config->getSystemValue('activity_log_exclude_users', []);
59+
if (empty($excludedUsers)) {
60+
return false;
61+
}
62+
$author = $event->getAuthor();
63+
if ($author === '' || !isset($excludedUsers[$author])) {
64+
return false;
65+
}
66+
$rule = $excludedUsers[$author];
67+
if (is_array($rule)) {
68+
return in_array($event->getType(), $rule, true);
69+
} else {
70+
$this->logger->warning(
71+
'activity_log_exclude_users rule for user "{user}" is not an array, skipping!',
72+
['app' => 'activity', 'user' => $author]
73+
);
74+
}
75+
return false;
76+
}
77+
4178
/**
4279
* Send an event into the activity stream
4380
*
4481
* @param IEvent $event
4582
* @return int
4683
*/
4784
public function send(IEvent $event): int {
48-
if ($event->getAffectedUser() === '') {
85+
if (!$this->shouldSend($event)) {
4986
return 0;
5087
}
5188

@@ -103,6 +140,10 @@ public function send(IEvent $event): int {
103140
* @throws Exception
104141
*/
105142
public function bulkSend(IEvent $event, array $affectedUsers): array {
143+
if ($this->isExcludedAuthor($event)) {
144+
return [];
145+
}
146+
106147
$this->connection->beginTransaction();
107148

108149
$activityIds = [];
@@ -169,8 +210,7 @@ public function bulkSend(IEvent $event, array $affectedUsers): array {
169210
* @return bool
170211
*/
171212
public function storeMail(IEvent $event, int $latestSendTime): bool {
172-
$affectedUser = $event->getAffectedUser();
173-
if ($affectedUser === '') {
213+
if (!$this->shouldSend($event)) {
174214
return false;
175215
}
176216

@@ -194,7 +234,7 @@ public function storeMail(IEvent $event, int $latestSendTime): bool {
194234
'amq_appid' => $event->getApp(),
195235
'amq_subject' => $event->getSubject(),
196236
'amq_subjectparams' => json_encode($event->getSubjectParameters()),
197-
'amq_affecteduser' => $affectedUser,
237+
'amq_affecteduser' => $event->getAffectedUser(),
198238
'amq_timestamp' => $event->getTimestamp(),
199239
'amq_type' => $event->getType(),
200240
'amq_latest_send' => $latestSendTime,

tests/DataTest.php

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,129 @@ public function testDeleteAffectedUserActivities(): void {
347347
$this->deleteTestActivities();
348348
}
349349

350+
public static function dataExcludedAuthor(): array {
351+
return [
352+
// author+type match → blocked
353+
['alice', 'target', 'file_created', ['alice' => ['file_created']], false],
354+
// type mismatch → allowed
355+
['alice', 'target', 'file_created', ['alice' => ['file_deleted']], true],
356+
// different user → allowed
357+
['bob', 'target', 'file_created', ['alice' => ['file_created']], true],
358+
// empty config → allowed
359+
['alice', 'target', 'file_created', [], true],
360+
// non-array rule → allowed
361+
['alice', 'target', 'file_created', ['alice' => 'file_created'], true],
362+
];
363+
}
364+
365+
#[DataProvider('dataExcludedAuthor')]
366+
public function testSendWithExcludedAuthor(string $author, string $affectedUser, string $type, array $excludedUsers, bool $expectedInsert): void {
367+
$this->deleteTestActivities();
368+
369+
$this->config->method('getSystemValue')
370+
->with('activity_log_exclude_users', [])
371+
->willReturn($excludedUsers);
372+
373+
$event = $this->realActivityManager->generateEvent();
374+
$event->setApp('test')
375+
->setType($type)
376+
->setAuthor($author)
377+
->setAffectedUser($affectedUser)
378+
->setSubject('subject');
379+
380+
$result = $this->data->send($event);
381+
$this->assertSame($expectedInsert, $result !== 0);
382+
383+
$qb = $this->dbConnection->getQueryBuilder();
384+
$row = $qb->select('user', 'affecteduser')
385+
->from('activity')
386+
->where($qb->expr()->eq('app', $qb->createNamedParameter('test')))
387+
->orderBy('activity_id', 'DESC')
388+
->executeQuery()
389+
->fetch();
390+
391+
if ($expectedInsert) {
392+
$this->assertEquals(['user' => $author, 'affecteduser' => $affectedUser], $row);
393+
} else {
394+
$this->assertFalse($row);
395+
}
396+
397+
$this->deleteTestActivities();
398+
}
399+
400+
#[DataProvider('dataExcludedAuthor')]
401+
public function testStoreMailWithExcludedAuthor(string $author, string $affectedUser, string $type, array $excludedUsers, bool $expectedInsert): void {
402+
$this->deleteTestMails();
403+
404+
$this->config->method('getSystemValue')
405+
->with('activity_log_exclude_users', [])
406+
->willReturn($excludedUsers);
407+
408+
$time = time();
409+
$event = $this->realActivityManager->generateEvent();
410+
$event->setApp('test')
411+
->setType($type)
412+
->setAuthor($author)
413+
->setAffectedUser($affectedUser)
414+
->setSubject('subject')
415+
->setTimestamp($time);
416+
417+
$this->assertSame($expectedInsert, $this->data->storeMail($event, $time + 10));
418+
419+
$qb = $this->dbConnection->getQueryBuilder();
420+
$row = $qb->select('amq_latest_send', 'amq_affecteduser')
421+
->from('activity_mq')
422+
->where($qb->expr()->eq('amq_appid', $qb->createNamedParameter('test')))
423+
->orderBy('mail_id', 'DESC')
424+
->executeQuery()
425+
->fetch();
426+
427+
if ($expectedInsert) {
428+
$this->assertEquals(['amq_latest_send' => $time + 10, 'amq_affecteduser' => $affectedUser], $row);
429+
} else {
430+
$this->assertFalse($row);
431+
}
432+
433+
$this->deleteTestMails();
434+
}
435+
436+
#[DataProvider('dataExcludedAuthor')]
437+
public function testBulkSendWithExcludedAuthor(string $author, string $_affectedUser, string $type, array $excludedUsers, bool $expectedInsert): void {
438+
$this->deleteTestActivities();
439+
440+
$this->config->method('getSystemValue')
441+
->with('activity_log_exclude_users', [])
442+
->willReturn($excludedUsers);
443+
444+
$event = $this->realActivityManager->generateEvent();
445+
$event->setApp('test')
446+
->setType($type)
447+
->setAuthor($author)
448+
->setSubject('subject')
449+
->setTimestamp(time());
450+
451+
$bulkUsers = ['user1', 'user2'];
452+
$result = $this->data->bulkSend($event, $bulkUsers);
453+
454+
if ($expectedInsert) {
455+
$this->assertCount(2, $result);
456+
$this->assertEqualsCanonicalizing($bulkUsers, array_values($result));
457+
} else {
458+
$this->assertEmpty($result);
459+
}
460+
461+
$qb = $this->dbConnection->getQueryBuilder();
462+
$count = (int)$qb->select($qb->func()->count('activity_id', 'count'))
463+
->from('activity')
464+
->where($qb->expr()->eq('app', $qb->createNamedParameter('test')))
465+
->executeQuery()
466+
->fetch()['count'];
467+
468+
$this->assertSame($expectedInsert ? 2 : 0, $count);
469+
470+
$this->deleteTestActivities();
471+
}
472+
350473
/**
351474
* Delete all testing activities
352475
*/

0 commit comments

Comments
 (0)