Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions framework/core/js/src/admin/components/PermissionGrid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,31 @@ export default class PermissionGrid<CustomAttrs extends IPermissionGridAttrs = I
60
);

items.add(
'hideOwnPosts',
Comment thread
OrdinaryJellyfish marked this conversation as resolved.
Outdated
{
icon: 'far fa-trash-alt',
label: app.translator.trans('core.admin.permissions.allow_delete_own_posts_label'),
setting: () => {
const minutes = parseInt(app.data.settings.allow_hide_own_posts, 10);

return SettingDropdown.component({
defaultLabel: minutes
? app.translator.trans('core.admin.permissions_controls.allow_some_minutes_button', { count: minutes })
: app.translator.trans('core.admin.permissions_controls.allow_indefinitely_button'),
key: 'allow_hide_own_posts',
options: [
{ value: '-1', label: app.translator.trans('core.admin.permissions_controls.allow_indefinitely_button') },
{ value: '10', label: app.translator.trans('core.admin.permissions_controls.allow_ten_minutes_button') },
{ value: 'reply', label: app.translator.trans('core.admin.permissions_controls.allow_until_reply_button') },
{ value: '0', label: app.translator.trans('core.admin.permissions_controls.allow_never_button') },
],
});
},
},
60
);

items.add(
'deletePosts',
{
Expand Down
5 changes: 4 additions & 1 deletion framework/core/locale/core.yml
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,7 @@ core:

# These translations are used in the Permissions page of the admin interface.
permissions:
allow_delete_own_posts_label: Allow deleting own posts
allow_post_editing_label: Allow post editing
allow_renaming_label: Allow renaming
create_access_token_label: Create access token
Expand Down Expand Up @@ -228,6 +229,7 @@ core:
# These translations are used in the dropdown menus on the Permissions page.
permissions_controls:
allow_indefinitely_button: Indefinitely
allow_never_button: => core.ref.never
allow_some_minutes_button: "{count, plural, one {For # minute} other {For # minutes}}"
allow_ten_minutes_button: For 10 minutes
allow_until_reply_button: Until next reply
Expand Down Expand Up @@ -489,7 +491,7 @@ core:
log_out_button: => core.ref.log_out
hide_access_token: Hide Token
last_activity: Last activity
never: Never
never: => core.ref.never
new_access_token_button: => core.ref.new_token
new_access_token_modal:
submit_button: Create Token
Expand Down Expand Up @@ -801,6 +803,7 @@ core:
log_in: Log In
log_out: Log Out
mark_all_as_read: Mark All as Read
never: Never
new_token: New Token
next_page: Next Page
notifications: Notifications
Expand Down
1 change: 1 addition & 0 deletions framework/core/src/Install/Steps/WriteSettings.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ private function getSettings()
private function getDefaults()
{
return [
'allow_delete_own_posts' => 'reply',
'allow_post_editing' => 'reply',
'allow_renaming' => '10',
'allow_sign_up' => '1',
Expand Down
10 changes: 9 additions & 1 deletion framework/core/src/Post/Access/PostPolicy.php
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,14 @@ public function edit(User $actor, Post $post)
*/
public function hide(User $actor, Post $post)
{
return $this->edit($actor, $post);
if ($post->user_id == $actor->id && (! $post->hidden_at || $post->hidden_user_id == $actor->id) && $actor->can('reply', $post->discussion)) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if we should drop the bit about only being able to hide when the discussion is still open 🤔

Suggested change
if ($post->user_id == $actor->id && (! $post->hidden_at || $post->hidden_user_id == $actor->id) && $actor->can('reply', $post->discussion)) {
if ($post->user_id == $actor->id && (! $post->hidden_at || $post->hidden_user_id == $actor->id)) {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried to keep the behavior close to the post-editing one for consistency so that's why that's there! I was wondering if it would be necessary or not.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, not sure, let's keep it as is for now, then we'll see I guess unless other core devs have an opinion on is.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd prefer to keep it. If a user can't participate in a discussion going forward, i don't think they should be able to participate retroactively either.

$allowHiding = $this->settings->get('allow_hide_own_posts');

if ($allowHiding === '-1'
|| ($allowHiding === 'reply' && $post->number >= $post->discussion->last_post_number)
|| (is_numeric($allowHiding) && $post->created_at->diffInMinutes(new Carbon) < $allowHiding)) {
return $this->allow();
}
}
}
}
100 changes: 100 additions & 0 deletions framework/core/tests/integration/policy/PostPolicyTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -121,4 +121,104 @@ public function edit_10_minutes()
$this->assertFalse($user->can('edit', $earlierPost));
$this->assertFalse($user->can('edit', $lastPost));
}

/**
* @test
*/
public function hide_indefinitely()
{
$this->setting('allow_hide_own_posts', '-1');
$this->app();

$user = User::findOrFail(2);
$earlierPost = Post::findOrFail(1);
$lastPost = Post::findOrFail(2);

// Date close to "now"
Carbon::setTestNow('2021-11-01 13:00:05');

$this->assertTrue($user->can('hide', $earlierPost));
$this->assertTrue($user->can('hide', $lastPost));

// Date further into the future
Carbon::setTestNow('2025-01-01 13:00:00');

$this->assertTrue($user->can('hide', $earlierPost));
$this->assertTrue($user->can('hide', $lastPost));
}

/**
* @test
*/
public function hide_until_reply()
{
$this->setting('allow_hide_own_posts', 'reply');
$this->app();

$user = User::findOrFail(2);
$earlierPost = Post::findOrFail(1);
$lastPost = Post::findOrFail(2);

// Date close to "now"
Carbon::setTestNow('2021-11-01 13:00:05');

$this->assertFalse($user->can('hide', $earlierPost));
$this->assertTrue($user->can('hide', $lastPost));

// Date further into the future
Carbon::setTestNow('2025-01-01 13:00:00');

$this->assertFalse($user->can('hide', $earlierPost));
$this->assertTrue($user->can('hide', $lastPost));
}

/**
* @test
*/
public function hide_10_minutes()
{
$this->setting('allow_hide_own_posts', '10');
$this->app();

$user = User::findOrFail(2);
$earlierPost = Post::findOrFail(1);
$lastPost = Post::findOrFail(2);

// Date close to "now"
Carbon::setTestNow('2021-11-01 13:00:05');

$this->assertTrue($user->can('hide', $earlierPost));
$this->assertTrue($user->can('hide', $lastPost));

// Date further into the future
Carbon::setTestNow('2025-01-01 13:00:00');

$this->assertFalse($user->can('hide', $earlierPost));
$this->assertFalse($user->can('hide', $lastPost));
}

/**
* @test
*/
public function hide_never()
{
$this->setting('allow_hide_own_posts', '0');
$this->app();

$user = User::findOrFail(2);
$earlierPost = Post::findOrFail(1);
$lastPost = Post::findOrFail(2);

// Date close to "now"
Carbon::setTestNow('2021-11-01 13:00:05');

$this->assertFalse($user->can('hide', $earlierPost));
$this->assertFalse($user->can('hide', $lastPost));

// Date further into the future
Carbon::setTestNow('2025-01-01 13:00:00');

$this->assertFalse($user->can('hide', $earlierPost));
$this->assertFalse($user->can('hide', $lastPost));
}
}