Skip to content
GitLab
Projects
Groups
Topics
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Register
Sign in
Toggle navigation
Menu
Paulo Avila
petruz-tasks
Commits
eae4ed0f
Commit
eae4ed0f
authored
Jun 10, 2026
by
Paulo Avila
Browse files
Inclusão de travas de seguraça para pastas
parent
f5fa1ac0
Changes
9
Hide whitespace changes
Inline
Side-by-side
src/app/(app)/workspaces/[id]/membro/[memberId]/page.tsx
View file @
eae4ed0f
...
@@ -103,17 +103,21 @@ export default async function MemberFolderPage({
...
@@ -103,17 +103,21 @@ export default async function MemberFolderPage({
</
p
>
</
p
>
</
div
>
</
div
>
</
div
>
</
div
>
<
TaskDialog
{
(
role
===
"
admin
"
||
!
member
||
member
.
UserId
===
user
.
id
)
&&
(
workspaceId
=
{
workspaceId
}
<
TaskDialog
members
=
{
members
}
workspaceId
=
{
workspaceId
}
defaultAssigneeId
=
{
member
?.
UserId
}
members
=
{
members
}
trigger
=
{
defaultAssigneeId
=
{
member
?.
UserId
}
<
Button
>
currentUserId
=
{
user
.
id
}
<
Plus
className
=
"mr-2 h-4 w-4"
/>
isAdmin
=
{
role
===
"
admin
"
}
Nova tarefa
trigger
=
{
</
Button
>
<
Button
>
}
<
Plus
className
=
"mr-2 h-4 w-4"
/>
/>
Nova tarefa
</
Button
>
}
/>
)
}
</
div
>
</
div
>
<
StatusSummary
tasks
=
{
tasks
}
/>
<
StatusSummary
tasks
=
{
tasks
}
/>
...
...
src/app/(app)/workspaces/[id]/page.tsx
View file @
eae4ed0f
...
@@ -81,6 +81,8 @@ export default async function WorkspacePage({
...
@@ -81,6 +81,8 @@ export default async function WorkspacePage({
<
TaskDialog
<
TaskDialog
workspaceId
=
{
workspaceId
}
workspaceId
=
{
workspaceId
}
members
=
{
members
}
members
=
{
members
}
currentUserId
=
{
user
.
id
}
isAdmin
=
{
isAdmin
}
trigger
=
{
trigger
=
{
<
Button
>
<
Button
>
<
Plus
className
=
"mr-2 h-4 w-4"
/>
<
Plus
className
=
"mr-2 h-4 w-4"
/>
...
@@ -104,6 +106,8 @@ export default async function WorkspacePage({
...
@@ -104,6 +106,8 @@ export default async function WorkspacePage({
tasks
=
{
tasks
}
tasks
=
{
tasks
}
members
=
{
members
}
members
=
{
members
}
workspaceId
=
{
workspaceId
}
workspaceId
=
{
workspaceId
}
currentUserId
=
{
user
.
id
}
isAdmin
=
{
isAdmin
}
/>
/>
</
TabsContent
>
</
TabsContent
>
<
TabsContent
value
=
"list"
className
=
"mt-4"
>
<
TabsContent
value
=
"list"
className
=
"mt-4"
>
...
...
src/app/favicon.ico
deleted
100644 → 0
View file @
f5fa1ac0
25.3 KB
src/app/icon.png
0 → 100644
View file @
eae4ed0f
25.5 KB
src/components/tasks/task-board.tsx
View file @
eae4ed0f
...
@@ -65,6 +65,8 @@ export function TaskBoard({
...
@@ -65,6 +65,8 @@ export function TaskBoard({
members
=
{
members
}
members
=
{
members
}
task
=
{
toFormValues
(
task
)
}
task
=
{
toFormValues
(
task
)
}
subtasks
=
{
subtasksByTask
[
task
.
Id
]
??
[]
}
subtasks
=
{
subtasksByTask
[
task
.
Id
]
??
[]
}
currentUserId
=
{
currentUserId
}
isAdmin
=
{
isAdmin
}
trigger
=
{
trigger
=
{
<
Button
<
Button
variant
=
"ghost"
variant
=
"ghost"
...
...
src/components/tasks/task-by-person.tsx
View file @
eae4ed0f
...
@@ -48,10 +48,14 @@ export function TaskByPerson({
...
@@ -48,10 +48,14 @@ export function TaskByPerson({
tasks
,
tasks
,
members
,
members
,
workspaceId
,
workspaceId
,
currentUserId
,
isAdmin
,
}:
{
}:
{
tasks
:
Task
[];
tasks
:
Task
[];
members
:
WorkspaceMember
[];
members
:
WorkspaceMember
[];
workspaceId
:
number
;
workspaceId
:
number
;
currentUserId
:
number
;
isAdmin
:
boolean
;
subtasksByTask
?:
Record
<
number
,
Subtask
[]
>
;
subtasksByTask
?:
Record
<
number
,
Subtask
[]
>
;
})
{
})
{
const
groups
:
PersonGroup
[]
=
members
.
map
((
member
)
=>
({
const
groups
:
PersonGroup
[]
=
members
.
map
((
member
)
=>
({
...
@@ -155,11 +159,14 @@ export function TaskByPerson({
...
@@ -155,11 +159,14 @@ export function TaskByPerson({
<
ChevronRight
className
=
"h-4 w-4 shrink-0 text-muted-foreground"
/>
<
ChevronRight
className
=
"h-4 w-4 shrink-0 text-muted-foreground"
/>
</
Link
>
</
Link
>
{
group
.
userId
!==
null
&&
(
{
group
.
userId
!==
null
&&
(
isAdmin
||
group
.
userId
===
currentUserId
)
&&
(
<
TaskDialog
<
TaskDialog
workspaceId
=
{
workspaceId
}
workspaceId
=
{
workspaceId
}
members
=
{
members
}
members
=
{
members
}
defaultAssigneeId
=
{
group
.
userId
}
defaultAssigneeId
=
{
group
.
userId
}
currentUserId
=
{
currentUserId
}
isAdmin
=
{
isAdmin
}
trigger
=
{
trigger
=
{
<
Button
<
Button
variant
=
"ghost"
variant
=
"ghost"
...
...
src/components/tasks/task-dialog.tsx
View file @
eae4ed0f
...
@@ -66,6 +66,8 @@ export function TaskDialog({
...
@@ -66,6 +66,8 @@ export function TaskDialog({
task
,
task
,
subtasks
,
subtasks
,
defaultAssigneeId
,
defaultAssigneeId
,
currentUserId
,
isAdmin
,
trigger
,
trigger
,
}:
{
}:
{
workspaceId
:
number
;
workspaceId
:
number
;
...
@@ -73,8 +75,17 @@ export function TaskDialog({
...
@@ -73,8 +75,17 @@ export function TaskDialog({
task
?:
TaskFormValues
;
task
?:
TaskFormValues
;
subtasks
?:
Subtask
[];
subtasks
?:
Subtask
[];
defaultAssigneeId
?:
number
;
defaultAssigneeId
?:
number
;
currentUserId
:
number
;
isAdmin
:
boolean
;
trigger
:
ReactNode
;
trigger
:
ReactNode
;
})
{
})
{
// Membros comuns só podem atribuir tarefas a si mesmos; mantém o
// responsável atual visível em modo edição.
const
selectableMembers
=
isAdmin
?
members
:
members
.
filter
(
(
m
)
=>
m
.
UserId
===
currentUserId
||
m
.
UserId
===
task
?.
assigneeId
);
const
[
open
,
setOpen
]
=
useState
(
false
);
const
[
open
,
setOpen
]
=
useState
(
false
);
const
action
=
task
const
action
=
task
?
updateTaskAction
.
bind
(
null
,
task
.
id
)
?
updateTaskAction
.
bind
(
null
,
task
.
id
)
...
@@ -175,7 +186,7 @@ export function TaskDialog({
...
@@ -175,7 +186,7 @@ export function TaskDialog({
<
SelectValue
placeholder
=
"Sem responsável"
/>
<
SelectValue
placeholder
=
"Sem responsável"
/>
</
SelectTrigger
>
</
SelectTrigger
>
<
SelectContent
>
<
SelectContent
>
{
m
embers
.
map
((
m
)
=>
(
{
selectableM
embers
.
map
((
m
)
=>
(
<
SelectItem
key
=
{
m
.
UserId
}
value
=
{
String
(
m
.
UserId
)
}
>
<
SelectItem
key
=
{
m
.
UserId
}
value
=
{
String
(
m
.
UserId
)
}
>
{
m
.
Name
}
{
m
.
Name
}
</
SelectItem
>
</
SelectItem
>
...
...
src/components/tasks/task-table.tsx
View file @
eae4ed0f
...
@@ -135,6 +135,8 @@ export function TaskTable({
...
@@ -135,6 +135,8 @@ export function TaskTable({
members
=
{
members
}
members
=
{
members
}
task
=
{
toFormValues
(
task
)
}
task
=
{
toFormValues
(
task
)
}
subtasks
=
{
subtasksByTask
[
task
.
Id
]
??
[]
}
subtasks
=
{
subtasksByTask
[
task
.
Id
]
??
[]
}
currentUserId
=
{
currentUserId
}
isAdmin
=
{
isAdmin
}
trigger
=
{
trigger
=
{
<
Button
<
Button
variant
=
"ghost"
variant
=
"ghost"
...
...
src/lib/actions.ts
View file @
eae4ed0f
...
@@ -12,7 +12,7 @@ import {
...
@@ -12,7 +12,7 @@ import {
import
{
import
{
assertCanEditTask
,
assertCanEditTask
,
assertWorkspaceAdmin
,
assertWorkspaceAdmin
,
asser
tWorkspace
Member
,
ge
tWorkspace
Role
,
requireUser
,
requireUser
,
}
from
"
./authz
"
;
}
from
"
./authz
"
;
import
*
as
data
from
"
./data
"
;
import
*
as
data
from
"
./data
"
;
...
@@ -265,7 +265,20 @@ export async function createTaskAction(
...
@@ -265,7 +265,20 @@ export async function createTaskAction(
if
(
!
parsed
.
success
)
return
{
error
:
firstError
(
parsed
.
error
)
};
if
(
!
parsed
.
success
)
return
{
error
:
firstError
(
parsed
.
error
)
};
try
{
try
{
await
assertWorkspaceMember
(
parsed
.
data
.
workspaceId
,
user
);
const
role
=
await
getWorkspaceRole
(
parsed
.
data
.
workspaceId
,
user
.
id
);
if
(
!
role
)
{
return
{
error
:
"
Você não tem acesso a este espaço de trabalho.
"
};
}
// Membros comuns só criam tarefas para si mesmos (ou sem responsável).
if
(
role
!==
"
admin
"
&&
parsed
.
data
.
assigneeId
!==
undefined
&&
parsed
.
data
.
assigneeId
!==
user
.
id
)
{
return
{
error
:
"
Apenas admins podem criar tarefas para outra pessoa.
"
,
};
}
await
data
.
createTask
(
await
data
.
createTask
(
{
{
workspaceId
:
parsed
.
data
.
workspaceId
,
workspaceId
:
parsed
.
data
.
workspaceId
,
...
@@ -303,6 +316,18 @@ export async function updateTaskAction(
...
@@ -303,6 +316,18 @@ export async function updateTaskAction(
const
task
=
await
data
.
getTask
(
taskId
);
const
task
=
await
data
.
getTask
(
taskId
);
if
(
!
task
)
return
{
error
:
"
Tarefa não encontrada.
"
};
if
(
!
task
)
return
{
error
:
"
Tarefa não encontrada.
"
};
await
assertCanEditTask
(
task
,
user
);
await
assertCanEditTask
(
task
,
user
);
// Membros comuns não podem transferir a tarefa para outra pessoa.
const
role
=
await
getWorkspaceRole
(
task
.
WorkspaceId
,
user
.
id
);
if
(
role
!==
"
admin
"
&&
parsed
.
data
.
assigneeId
!==
undefined
&&
parsed
.
data
.
assigneeId
!==
user
.
id
&&
parsed
.
data
.
assigneeId
!==
task
.
AssigneeId
)
{
return
{
error
:
"
Apenas admins podem atribuir tarefas a outra pessoa.
"
,
};
}
await
data
.
updateTask
(
taskId
,
{
await
data
.
updateTask
(
taskId
,
{
workspaceId
:
task
.
WorkspaceId
,
workspaceId
:
task
.
WorkspaceId
,
title
:
parsed
.
data
.
title
,
title
:
parsed
.
data
.
title
,
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment