diff --git a/extensions/tags/composer.json b/extensions/tags/composer.json index 91adda6616..ccbc8843dc 100644 --- a/extensions/tags/composer.json +++ b/extensions/tags/composer.json @@ -79,7 +79,8 @@ }, "require-dev": { "flarum/core": "*@dev", - "flarum/testing": "^1.0.0" + "flarum/testing": "^1.0.0", + "flarum/suspend": "*@dev" }, "repositories": [ { diff --git a/extensions/tags/src/Access/GlobalPolicy.php b/extensions/tags/src/Access/GlobalPolicy.php index feb05432a2..40532ed55a 100644 --- a/extensions/tags/src/Access/GlobalPolicy.php +++ b/extensions/tags/src/Access/GlobalPolicy.php @@ -42,6 +42,15 @@ public function can(User $actor, string $ability) return $this->allow(); } + if ($ability === 'startDiscussion') { + $minPrimaryTags = (int) $this->settings->get('flarum-tags.min_primary_tags'); + $minSecondaryTags = (int) $this->settings->get('flarum-tags.min_secondary_tags'); + + if ($minPrimaryTags === 0 && $minSecondaryTags === 0) { + return; + } + } + if (in_array($ability, ['viewForum', 'startDiscussion'])) { if (! isset($enoughPrimary[$actor->id][$ability])) { $primaryTagsWhereNeedsPermission = $this->settings->get('flarum-tags.min_primary_tags'); diff --git a/extensions/tags/tests/integration/forum/ForumAttributeTest.php b/extensions/tags/tests/integration/forum/ForumAttributeTest.php new file mode 100644 index 0000000000..21129f1f7d --- /dev/null +++ b/extensions/tags/tests/integration/forum/ForumAttributeTest.php @@ -0,0 +1,91 @@ +extension('flarum-tags'); + $this->extension('flarum-suspend'); + + $this->prepareDatabase([ + 'tags' => $this->tags(), + 'users' => [ + $this->normalUser(), + ['id' => 3, 'username' => 'suspended-user', 'email' => 'suspended-user@machine.local', 'suspended_until' => '2043-11-17 22:05:23', 'is_email_confirmed' => 1], + ] + ]); + } + + public function canStartDiscussionProvider() + { + return [ + 'admin user, min 0/0' => ['authenticatedAs' => 1, 'minPrimary' => 0, 'minSecondary' => 0, 'expected' => true], + 'normal user, min 0/0' => ['authenticatedAs' => 2, 'minPrimary' => 0, 'minSecondary' => 0, 'expected' => true], + 'suspended user, min 0/0' => ['authenticatedAs' => 3, 'minPrimary' => 0, 'minSecondary' => 0, 'expected' => false], + 'guest user, min 0/0' => ['authenticatedAs' => null, 'minPrimary' => 0, 'minSecondary' => 0, 'expected' => false], + + 'admin user, min 1/0' => ['authenticatedAs' => 1, 'minPrimary' => 1, 'minSecondary' => 0, 'expected' => true], + 'normal user, min 1/0' => ['authenticatedAs' => 2, 'minPrimary' => 1, 'minSecondary' => 0, 'expected' => true], + 'suspended user, min 1/0' => ['authenticatedAs' => 3, 'minPrimary' => 1, 'minSecondary' => 0, 'expected' => false], + 'guest user, min 1/0' => ['authenticatedAs' => null, 'minPrimary' => 1, 'minSecondary' => 0, 'expected' => false], + + 'admin user, min 0/1' => ['authenticatedAs' => 1, 'minPrimary' => 0, 'minSecondary' => 1, 'expected' => true], + 'normal user, min 0/1' => ['authenticatedAs' => 2, 'minPrimary' => 0, 'minSecondary' => 1, 'expected' => true], + 'suspended user, min 0/1' => ['authenticatedAs' => 3, 'minPrimary' => 0, 'minSecondary' => 1, 'expected' => false], + 'guest user, min 0/1' => ['authenticatedAs' => null, 'minPrimary' => 0, 'minSecondary' => 1, 'expected' => false], + + 'admin user, min 1/1' => ['authenticatedAs' => 1, 'minPrimary' => 1, 'minSecondary' => 1, 'expected' => true], + 'normal user, min 1/1' => ['authenticatedAs' => 2, 'minPrimary' => 1, 'minSecondary' => 1, 'expected' => true], + 'suspended user, min 1/1' => ['authenticatedAs' => 3, 'minPrimary' => 1, 'minSecondary' => 1, 'expected' => false], + 'guest user, min 1/1' => ['authenticatedAs' => null, 'minPrimary' => 1, 'minSecondary' => 1, 'expected' => false], + ]; + } + + /** + * @test + * + * @dataProvider canStartDiscussionProvider + */ + public function it_returns_the_expected_can_start_discussion_attribute( + ?int $authenticatedAs, + int $minPrimary, + int $minSecondary, + bool $expected + ) { + $this->setting('flarum-tags.min_primary_tags', $minPrimary); + $this->setting('flarum-tags.min_secondary_tags', $minSecondary); + + $response = $this->send( + $this->request('GET', '/api', [ + 'authenticatedAs' => $authenticatedAs, + ]) + ); + + $this->assertEquals(200, $response->getStatusCode()); + + $json = json_decode($response->getBody()->getContents(), true); + $this->assertEquals($expected, Arr::get($json, 'data.attributes.canStartDiscussion')); + } +}