Skip to content

Commit e8632a5

Browse files
committed
permissions
1 parent a46ae32 commit e8632a5

52 files changed

Lines changed: 1806 additions & 454 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

TODO.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# TODO
22

3+
- permissions per feature: embed permissions in paseto token for future verification in middleware
4+
35
## Content
46

57
- page vs loops.so
@@ -9,7 +11,6 @@
911

1012
## Eventual features
1113

12-
- permissions with roles per workspace
1314
- better design for system email
1415
- store last cron timestamp in DB and render an alert if it's not running (only in production)
1516
- add contact_list reason string

config/config.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import (
1010
"github.com/spf13/viper"
1111
)
1212

13-
const VERSION = "5.0"
13+
const VERSION = "6.0"
1414

1515
type Config struct {
1616
Server ServerConfig
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
import { useState, useEffect } from 'react'
2+
import { Modal, Button, Table, Switch, App } from 'antd'
3+
import { WorkspaceMember, UserPermissions } from '../../services/api/types'
4+
import { workspaceService } from '../../services/api/workspace'
5+
6+
interface EditPermissionsModalProps {
7+
visible: boolean
8+
member: WorkspaceMember | null
9+
workspaceId: string
10+
onClose: () => void
11+
onSuccess: () => void
12+
}
13+
14+
export function EditPermissionsModal({
15+
visible,
16+
member,
17+
workspaceId,
18+
onClose,
19+
onSuccess
20+
}: EditPermissionsModalProps) {
21+
const [permissions, setPermissions] = useState<UserPermissions>({} as UserPermissions)
22+
const [saving, setSaving] = useState(false)
23+
const { message } = App.useApp()
24+
25+
// Initialize permissions when modal opens
26+
useEffect(() => {
27+
if (member && visible) {
28+
// Use permissions from member data
29+
setPermissions(member.permissions)
30+
}
31+
}, [member, visible])
32+
33+
const handleSavePermissions = async () => {
34+
if (!member) return
35+
36+
setSaving(true)
37+
try {
38+
await workspaceService.setUserPermissions({
39+
workspace_id: workspaceId,
40+
user_id: member.user_id,
41+
permissions: permissions
42+
})
43+
44+
message.success('Permissions updated successfully')
45+
onSuccess()
46+
onClose()
47+
} catch (error) {
48+
console.error('Failed to update permissions', error)
49+
message.error('Failed to update permissions')
50+
} finally {
51+
setSaving(false)
52+
}
53+
}
54+
55+
const updatePermission = (resource: string, type: 'read' | 'write', value: boolean) => {
56+
setPermissions((prev) => ({
57+
...prev,
58+
[resource]: {
59+
...(prev as any)[resource],
60+
[type]: value
61+
}
62+
}))
63+
}
64+
65+
// Helper function to create permissions table data
66+
const createPermissionsTableData = (permissions: UserPermissions) => {
67+
return Object.entries(permissions).map(([resource, perms]) => ({
68+
key: resource,
69+
resource: resource.replace('_', ' ').replace(/\b\w/g, (l) => l.toUpperCase()),
70+
read: perms.read,
71+
write: perms.write
72+
}))
73+
}
74+
75+
// Permissions table columns
76+
const permissionsColumns = [
77+
{
78+
title: 'Resource',
79+
dataIndex: 'resource',
80+
key: 'resource',
81+
width: '40%'
82+
},
83+
{
84+
title: 'Read',
85+
dataIndex: 'read',
86+
key: 'read',
87+
width: '30%',
88+
render: (value: boolean, record: any) => (
89+
<Switch
90+
checked={value}
91+
onChange={(checked) => updatePermission(record.key, 'read', checked)}
92+
size="small"
93+
/>
94+
)
95+
},
96+
{
97+
title: 'Write',
98+
dataIndex: 'write',
99+
key: 'write',
100+
width: '30%',
101+
render: (value: boolean, record: any) => (
102+
<Switch
103+
checked={value}
104+
onChange={(checked) => updatePermission(record.key, 'write', checked)}
105+
size="small"
106+
/>
107+
)
108+
}
109+
]
110+
111+
return (
112+
<Modal
113+
title={`Edit Permissions for ${member?.email}`}
114+
open={visible}
115+
onCancel={onClose}
116+
width={600}
117+
footer={[
118+
<Button key="cancel" onClick={onClose}>
119+
Cancel
120+
</Button>,
121+
<Button key="save" type="primary" onClick={handleSavePermissions} loading={saving}>
122+
Save Permissions
123+
</Button>
124+
]}
125+
>
126+
<Table
127+
dataSource={createPermissionsTableData(permissions)}
128+
columns={permissionsColumns}
129+
pagination={false}
130+
size="small"
131+
className="border border-gray-200 rounded-md my-8"
132+
/>
133+
</Modal>
134+
)
135+
}

0 commit comments

Comments
 (0)