feat: 限制系统化待办删除权限 (#1055)
This commit is contained in:
parent
14adc83014
commit
d803d97c19
@ -45,6 +45,7 @@ class SystemizationTodos extends Controller
|
||||
'秋香',
|
||||
'待定',
|
||||
];
|
||||
private const TODO_DELETE_ACCOUNTS = ['江陵', 'jiangling'];
|
||||
private const COLUMN_WIDTHS_SETTING = 'business.systemization_todos.column_widths';
|
||||
private const COLUMN_WIDTH_KEYS = [
|
||||
'type',
|
||||
@ -156,6 +157,7 @@ class SystemizationTodos extends Controller
|
||||
)),
|
||||
'todoColumnWidths' => $this->columnWidths(),
|
||||
'todoSummary' => $summary,
|
||||
'canDeleteTodos' => $this->canDeleteTodos(),
|
||||
'todoRoutes' => [
|
||||
'store' => route('business.systemization-todos.store'),
|
||||
'update' => route('business.systemization-todos.update', ['todo' => '__TODO__']),
|
||||
@ -800,6 +802,8 @@ class SystemizationTodos extends Controller
|
||||
|
||||
public function destroy(SystemizationTodo $todo): RedirectResponse
|
||||
{
|
||||
abort_unless($this->canDeleteTodos(), 403, '只有江陵可以删除待办事项。');
|
||||
|
||||
DB::transaction(function () use ($todo): void {
|
||||
$before = $this->audit->snapshot($todo, true);
|
||||
$todo->update(['updated_by' => user_id()]);
|
||||
@ -819,6 +823,13 @@ class SystemizationTodos extends Controller
|
||||
return $this->backToPage('待办事项已删除。');
|
||||
}
|
||||
|
||||
private function canDeleteTodos(): bool
|
||||
{
|
||||
$accountName = mb_strtolower(trim((string) (user()?->name ?? '')));
|
||||
|
||||
return in_array($accountName, self::TODO_DELETE_ACCOUNTS, true);
|
||||
}
|
||||
|
||||
public function batchUpdateCells(Request $request): JsonResponse
|
||||
{
|
||||
$data = $request->validate([
|
||||
|
||||
@ -728,14 +728,16 @@
|
||||
@disabled((int) $item->item_sequence >= (int) $item->content_count)>
|
||||
<span class="material-icons-outlined" aria-hidden="true">arrow_downward</span>
|
||||
</button>
|
||||
<button type="button" class="sys-todo-table__row-action sys-todo-table__row-action--danger"
|
||||
data-sys-todo-grid-delete
|
||||
data-sys-todo-grid-delete-url="{{ route('business.systemization-todos.destroy', ['todo' => $item->id]) }}"
|
||||
data-sys-todo-grid-delete-title="{{ $titleLabels[$loop->index] }}"
|
||||
title="删除这一行"
|
||||
aria-label="删除第 {{ (int) $item->item_sequence }} 条待办">
|
||||
<span class="material-icons-outlined" aria-hidden="true">delete_outline</span>
|
||||
</button>
|
||||
@if ($canDeleteTodos)
|
||||
<button type="button" class="sys-todo-table__row-action sys-todo-table__row-action--danger"
|
||||
data-sys-todo-grid-delete
|
||||
data-sys-todo-grid-delete-url="{{ route('business.systemization-todos.destroy', ['todo' => $item->id]) }}"
|
||||
data-sys-todo-grid-delete-title="{{ $titleLabels[$loop->index] }}"
|
||||
title="删除这一行"
|
||||
aria-label="删除第 {{ (int) $item->item_sequence }} 条待办">
|
||||
<span class="material-icons-outlined" aria-hidden="true">delete_outline</span>
|
||||
</button>
|
||||
@endif
|
||||
</span>
|
||||
</td>
|
||||
<td class="sys-todo-table__title" title="点击待办文字直接编辑">
|
||||
@ -1022,7 +1024,9 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="sys-todo-dialog__foot">
|
||||
<button type="button" class="sys-todo-dialog__delete" data-sys-todo-open-delete hidden>删除待办</button>
|
||||
@if ($canDeleteTodos)
|
||||
<button type="button" class="sys-todo-dialog__delete" data-sys-todo-open-delete hidden>删除待办</button>
|
||||
@endif
|
||||
<button type="button" data-sys-todo-close>取消</button>
|
||||
<button type="submit">保存</button>
|
||||
</div>
|
||||
@ -2032,7 +2036,7 @@
|
||||
title.textContent = currentTodoId
|
||||
? '编辑待办'
|
||||
: (payload && payload.afterSequence ? '在第 ' + payload.afterSequence + ' 条后新增待办' : '新增待办');
|
||||
deleteButton.hidden = !currentTodoId;
|
||||
if (deleteButton) deleteButton.hidden = !currentTodoId;
|
||||
if (!currentTodoId) {
|
||||
payload = Object.assign({}, payload || {});
|
||||
if (!payload.owner && activeTodoFilters.owners.length) {
|
||||
|
||||
@ -18,6 +18,7 @@ class SystemizationTodosTest extends FeatureTestCase
|
||||
{
|
||||
Storage::fake('uploads');
|
||||
|
||||
$this->loginAsSystemizationTodoDeleter();
|
||||
$pageResponse = $this->loginAs()
|
||||
->get(route('business.pages.show', [
|
||||
'section' => 'other',
|
||||
@ -1965,6 +1966,7 @@ class SystemizationTodosTest extends FeatureTestCase
|
||||
|
||||
public function test_manual_changes_are_listed_in_operation_history_and_csv(): void
|
||||
{
|
||||
$this->loginAsSystemizationTodoDeleter();
|
||||
$this->loginAs();
|
||||
|
||||
$this->post(route('business.systemization-todos.store'), [
|
||||
@ -2014,6 +2016,45 @@ class SystemizationTodosTest extends FeatureTestCase
|
||||
$this->assertStringNotContainsString('新增:', $csv);
|
||||
}
|
||||
|
||||
public function test_only_jiangling_can_see_or_use_todo_delete_entry_points(): void
|
||||
{
|
||||
$this->loginAs();
|
||||
$todo = $this->createTodo('收入', '删除权限测试', '普通账号不得删除', '2026-11-30', 1);
|
||||
|
||||
$this->get(route('business.pages.show', [
|
||||
'section' => 'other',
|
||||
'page' => 'systemization-todos',
|
||||
]))->assertOk()
|
||||
->assertDontSee('data-sys-todo-grid-delete-url="', false)
|
||||
->assertDontSee('data-sys-todo-open-delete hidden', false);
|
||||
|
||||
$this->withExceptionHandling()
|
||||
->delete(route('business.systemization-todos.destroy', ['todo' => $todo->id]))
|
||||
->assertForbidden();
|
||||
|
||||
$this->assertNotSoftDeleted('business_systemization_todos', ['id' => $todo->id]);
|
||||
}
|
||||
|
||||
public function test_jiangling_can_delete_todos(): void
|
||||
{
|
||||
$this->user->update(['name' => '江陵']);
|
||||
$this->user->refresh();
|
||||
$this->loginAs();
|
||||
$todo = $this->createTodo('收入', '删除权限测试', '江陵可以删除', '2026-11-30', 1);
|
||||
|
||||
$this->get(route('business.pages.show', [
|
||||
'section' => 'other',
|
||||
'page' => 'systemization-todos',
|
||||
]))->assertOk()
|
||||
->assertSee('data-sys-todo-grid-delete-url="', false)
|
||||
->assertSee('data-sys-todo-open-delete hidden', false);
|
||||
|
||||
$this->delete(route('business.systemization-todos.destroy', ['todo' => $todo->id]))
|
||||
->assertRedirect();
|
||||
|
||||
$this->assertSoftDeleted('business_systemization_todos', ['id' => $todo->id]);
|
||||
}
|
||||
|
||||
public function test_operation_history_starts_from_today(): void
|
||||
{
|
||||
$this->loginAs();
|
||||
@ -2280,6 +2321,12 @@ class SystemizationTodosTest extends FeatureTestCase
|
||||
]);
|
||||
}
|
||||
|
||||
private function loginAsSystemizationTodoDeleter(): void
|
||||
{
|
||||
$this->user->update(['name' => '江陵']);
|
||||
$this->user->refresh();
|
||||
}
|
||||
|
||||
private function writeWorkbook(string $path, array $rows): void
|
||||
{
|
||||
$spreadsheet = new Spreadsheet();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user