Skip to content

Commit 96a0cc3

Browse files
committed
feat: track overly long activities
For activities with very long content, track them and add them to the setup check Signed-off-by: Anna Larch <anna@nextcloud.com>
1 parent a17f4d4 commit 96a0cc3

File tree

4 files changed

+169
-64
lines changed

4 files changed

+169
-64
lines changed

lib/private/Activity/Event.php

Lines changed: 43 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -11,59 +11,43 @@
1111

1212
use OCP\Activity\Exceptions\InvalidValueException;
1313
use OCP\Activity\IEvent;
14+
use OCP\IAppConfig;
1415
use OCP\RichObjectStrings\InvalidObjectExeption;
1516
use OCP\RichObjectStrings\IRichTextFormatter;
1617
use OCP\RichObjectStrings\IValidator;
18+
use Psr\Log\LoggerInterface;
1719

1820
class Event implements IEvent {
19-
/** @var string */
20-
protected $app = '';
21-
/** @var string */
22-
protected $type = '';
23-
/** @var string */
24-
protected $affectedUser = '';
25-
/** @var string */
26-
protected $author = '';
27-
/** @var int */
28-
protected $timestamp = 0;
29-
/** @var string */
30-
protected $subject = '';
31-
/** @var array */
32-
protected $subjectParameters = [];
33-
/** @var string */
34-
protected $subjectParsed = '';
35-
/** @var string */
36-
protected $subjectRich = '';
21+
protected string $app = '';
22+
protected string $type = '';
23+
protected string $affectedUser = '';
24+
protected string $author = '';
25+
protected int $timestamp = 0;
26+
protected string $subject = '';
27+
protected array $subjectParameters = [];
28+
protected string $subjectParsed = '';
29+
protected string $subjectRich = '';
3730
/** @var array<string, array<string, string>> */
38-
protected $subjectRichParameters = [];
39-
/** @var string */
40-
protected $message = '';
41-
/** @var array */
42-
protected $messageParameters = [];
43-
/** @var string */
44-
protected $messageParsed = '';
45-
/** @var string */
46-
protected $messageRich = '';
31+
protected array $subjectRichParameters = [];
32+
protected string $message = '';
33+
protected array $messageParameters = [];
34+
protected string $messageParsed = '';
35+
protected string $messageRich = '';
4736
/** @var array<string, array<string, string>> */
48-
protected $messageRichParameters = [];
49-
/** @var string */
50-
protected $objectType = '';
37+
protected array $messageRichParameters = [];
38+
protected string $objectType = '';
5139
protected string|int $objectId = 0;
52-
/** @var string */
53-
protected $objectName = '';
54-
/** @var string */
55-
protected $link = '';
56-
/** @var string */
57-
protected $icon = '';
58-
/** @var bool */
59-
protected $generateNotification = true;
60-
61-
/** @var IEvent|null */
62-
protected $child;
40+
protected string $objectName = '';
41+
protected string $link = '';
42+
protected string $icon = '';
43+
protected bool $generateNotification = true;
44+
protected ?IEvent $child;
6345

6446
public function __construct(
6547
protected IValidator $richValidator,
6648
protected IRichTextFormatter $richTextFormatter,
49+
protected LoggerInterface $logger,
50+
protected IAppConfig $appConfig,
6751
) {
6852
}
6953

@@ -164,6 +148,24 @@ public function setSubject(string $subject, array $parameters = []): IEvent {
164148
if (isset($subject[255])) {
165149
throw new InvalidValueException('subject');
166150
}
151+
152+
$counter = $this->appConfig->getValueInt('activity', 'overly_long_activities', 0);
153+
$return = [];
154+
array_walk_recursive($parameters, static function ($a) use (&$return) { $return[] = $a; });
155+
$parameter = implode('', $return);
156+
157+
if (strlen($parameter) > 4000) {
158+
$counter++;
159+
$this->logger->error('Activity with over 4000 characters detected', ['app' => $this->getApp()]);
160+
} elseif (strlen($parameter) > 2000) {
161+
$counter++;
162+
$this->logger->warning('Activity with over 2000 characters detected', ['app' => $this->getApp()]);
163+
}
164+
165+
if ($counter !== 0) {
166+
$this->appConfig->setValueInt('activity', 'overly_long_activities', $counter);
167+
}
168+
167169
$this->subject = $subject;
168170
$this->subjectParameters = $parameters;
169171
return $this;

lib/private/Activity/Manager.php

Lines changed: 19 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -19,27 +19,21 @@
1919
use OCP\Activity\IProvider;
2020
use OCP\Activity\ISetting;
2121
use OCP\AppFramework\Utility\ITimeFactory;
22+
use OCP\IAppConfig;
2223
use OCP\IConfig;
2324
use OCP\IL10N;
2425
use OCP\IRequest;
2526
use OCP\IUser;
2627
use OCP\IUserSession;
2728
use OCP\RichObjectStrings\IRichTextFormatter;
2829
use OCP\RichObjectStrings\IValidator;
30+
use Psr\Log\LoggerInterface;
2931

3032
class Manager implements IManager {
31-
32-
/** @var string */
33-
protected $formattingObjectType;
34-
35-
/** @var int|string */
36-
protected $formattingObjectId;
37-
38-
/** @var bool */
39-
protected $requirePNG = false;
40-
41-
/** @var string */
42-
protected $currentUserId;
33+
protected string $formattingObjectType;
34+
protected string|int $formattingObjectId;
35+
protected bool $requirePNG = false;
36+
protected ?string $currentUserId;
4337

4438
public function __construct(
4539
protected IRequest $request,
@@ -49,17 +43,20 @@ public function __construct(
4943
protected IRichTextFormatter $richTextFormatter,
5044
protected IL10N $l10n,
5145
protected ITimeFactory $timeFactory,
46+
protected IAppConfig $appConfig,
47+
protected LoggerInterface $logger,
5248
) {
49+
$this->currentUserId = $this->session->getUser()?->getUID();
5350
}
5451

5552
/** @var \Closure[] */
56-
private $consumersClosures = [];
53+
private array $consumersClosures = [];
5754

5855
/** @var IConsumer[] */
59-
private $consumers = [];
56+
private array $consumers = [];
6057

6158
/**
62-
* @return \OCP\Activity\IConsumer[]
59+
* @return IConsumer[]
6360
*/
6461
protected function getConsumers(): array {
6562
if (!empty($this->consumers)) {
@@ -92,7 +89,7 @@ protected function getConsumers(): array {
9289
* @return IEvent
9390
*/
9491
public function generateEvent(): IEvent {
95-
return new Event($this->validator, $this->richTextFormatter);
92+
return new Event($this->validator, $this->richTextFormatter, $this->logger, $this->appConfig);
9693
}
9794

9895
/**
@@ -163,10 +160,10 @@ public function registerConsumer(\Closure $callable): void {
163160
}
164161

165162
/** @var string[] */
166-
protected $filterClasses = [];
163+
protected array $filterClasses = [];
167164

168165
/** @var IFilter[] */
169-
protected $filters = [];
166+
protected array $filters = [];
170167

171168
/**
172169
* @param string $filter Class must implement OCA\Activity\IFilter
@@ -210,10 +207,10 @@ public function getFilterById(string $id): IFilter {
210207
}
211208

212209
/** @var string[] */
213-
protected $providerClasses = [];
210+
protected array $providerClasses = [];
214211

215212
/** @var IProvider[] */
216-
protected $providers = [];
213+
protected array $providers = [];
217214

218215
/**
219216
* @param string $provider Class must implement OCA\Activity\IProvider
@@ -244,10 +241,10 @@ public function getProviders(): array {
244241
}
245242

246243
/** @var string[] */
247-
protected $settingsClasses = [];
244+
protected array $settingsClasses = [];
248245

249246
/** @var ISetting[] */
250-
protected $settings = [];
247+
protected array $settings = [];
251248

252249
/**
253250
* @param string $setting Class must implement OCA\Activity\ISetting

lib/private/Server.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -633,13 +633,15 @@ public function __construct($webRoot, \OC\Config $config) {
633633
$this->registerService(\OCP\Activity\IManager::class, function (Server $c) {
634634
$l10n = $this->get(IFactory::class)->get('lib');
635635
return new \OC\Activity\Manager(
636-
$c->getRequest(),
636+
$c->get(IRequest::class),
637637
$c->get(IUserSession::class),
638638
$c->get(\OCP\IConfig::class),
639639
$c->get(IValidator::class),
640640
$c->get(IRichTextFormatter::class),
641641
$l10n,
642642
$c->get(ITimeFactory::class),
643+
$c->get(IAppConfig::class),
644+
$c->get(LoggerInterface::class),
643645
);
644646
});
645647

tests/lib/Activity/ManagerTest.php

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,13 @@
1010

1111
namespace Test\Activity;
1212

13+
use OC;
1314
use OC\Activity\Manager;
1415
use OCP\Activity\Exceptions\IncompleteActivityException;
1516
use OCP\Activity\IConsumer;
1617
use OCP\Activity\IEvent;
1718
use OCP\AppFramework\Utility\ITimeFactory;
19+
use OCP\IAppConfig;
1820
use OCP\IConfig;
1921
use OCP\IL10N;
2022
use OCP\IRequest;
@@ -23,6 +25,7 @@
2325
use OCP\RichObjectStrings\IRichTextFormatter;
2426
use OCP\RichObjectStrings\IValidator;
2527
use PHPUnit\Framework\MockObject\MockObject;
28+
use Psr\Log\LoggerInterface;
2629
use Test\TestCase;
2730

2831
class ManagerTest extends TestCase {
@@ -34,6 +37,8 @@ class ManagerTest extends TestCase {
3437
protected IValidator&MockObject $validator;
3538
protected IRichTextFormatter&MockObject $richTextFormatter;
3639
private ITimeFactory&MockObject $time;
40+
private IAppConfig $appConfig;
41+
private LoggerInterface&MockObject $logger;
3742

3843
protected function setUp(): void {
3944
parent::setUp();
@@ -44,6 +49,8 @@ protected function setUp(): void {
4449
$this->validator = $this->createMock(IValidator::class);
4550
$this->richTextFormatter = $this->createMock(IRichTextFormatter::class);
4651
$this->time = $this->createMock(ITimeFactory::class);
52+
$this->appConfig = OC::$server->get(IAppConfig::class);
53+
$this->logger = $this->createMock(LoggerInterface::class);
4754

4855
$this->activityManager = new Manager(
4956
$this->request,
@@ -53,6 +60,8 @@ protected function setUp(): void {
5360
$this->richTextFormatter,
5461
$this->createMock(IL10N::class),
5562
$this->time,
63+
$this->appConfig,
64+
$this->logger,
5665
);
5766

5867
$this->assertSame([], self::invokePrivate($this->activityManager, 'getConsumers'));
@@ -291,6 +300,101 @@ public function testPublishAllManually(): void {
291300

292301
$this->activityManager->publish($event);
293302
}
303+
304+
public function testPublishWithSuperLongNestedParams(): void {
305+
$this->appConfig->setValueInt('activity', 'overly_long_activities', 0);
306+
$params = [
307+
'level_one' => [
308+
'title' => 'Lorem ipsum dolor sit amet',
309+
'intro' => 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.',
310+
'level_two' => [
311+
[
312+
'heading' => 'Sed ut perspiciatis unde omnis',
313+
'body' => 'Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt.'
314+
],
315+
[
316+
'heading' => 'Neque porro quisquam est',
317+
'body' => 'Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam.'
318+
]
319+
]
320+
],
321+
'level_three' => [
322+
'section_a' => [
323+
'text' => 'At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga.',
324+
'more_text' => 'Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus id quod maxime placeat facere possimus, omnis voluptas assumenda est, omnis dolor repellendus.'
325+
],
326+
'section_b' => [
327+
'paragraphs' => [
328+
'Temporibus autem quibusdam et aut officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et molestiae non recusandae. Itaque earum rerum hic tenetur a sapiente delectus.',
329+
'Ut aut reiciendis voluptatibus maiores alias consequatur aut perferendis doloribus asperiores repellat. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',
330+
'Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.'
331+
]
332+
]
333+
],
334+
'level_four' => [
335+
'deep' => [
336+
'deeper' => [
337+
'block_one' => 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam.',
338+
'block_two' => 'Eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit.',
339+
'block_three' => 'Sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit.'
340+
]
341+
]
342+
],
343+
'level_five' => [
344+
'massive_text' => 'Sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur. At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus id quod maxime placeat facere possimus.'
345+
],
346+
'level_six' => [
347+
'repeat_blocks' => [
348+
[
349+
'text' => 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.'
350+
],
351+
[
352+
'text' => 'Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollitia animi.'
353+
],
354+
[
355+
'text' => 'Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo.'
356+
]
357+
]
358+
]
359+
];
360+
361+
$event = $event2 = $this->activityManager->generateEvent();
362+
$event->setApp('test_app')
363+
->setType('test_type')
364+
->setAffectedUser('test_affected')
365+
->setAuthor('test_author')
366+
->setTimestamp(1337)
367+
->setSubject('test_subject', $params)
368+
->setMessage('test_message', ['test_message_params'])
369+
->setObject('test_object_type', 42, 'test_object_name')
370+
->setLink('test_link');
371+
372+
$this->assertEquals(1, $this->appConfig->getValueInt('activity', 'overly_long_activities'));
373+
374+
$event2->setApp('test_app')
375+
->setType('test_type')
376+
->setAffectedUser('test_affected')
377+
->setAuthor('test_author')
378+
->setTimestamp(1337)
379+
->setSubject('test_subject', $params)
380+
->setMessage('test_message', ['test_message_params'])
381+
->setObject('test_object_type', 42, 'test_object_name')
382+
->setLink('test_link');
383+
384+
$consumer = $this->getMockBuilder('OCP\Activity\IConsumer')
385+
->disableOriginalConstructor()
386+
->getMock();
387+
$consumer->method('receive');
388+
$this->activityManager->registerConsumer(function () use ($consumer) {
389+
return $consumer;
390+
});
391+
392+
$this->activityManager->publish($event);
393+
$this->activityManager->publish($event2);
394+
$this->assertEquals(2, $this->appConfig->getValueInt('activity', 'overly_long_activities'));
395+
$this->appConfig->setValueInt('activity', 'overly_long_activities', 0);
396+
397+
}
294398
}
295399

296400
class NoOpConsumer implements IConsumer {

0 commit comments

Comments
 (0)