Scopes.tsx209 lines · main
1import { OAuthScope } from '@supabase/shared-types/out/constants'
2import { ChevronDown } from 'lucide-react'
3import { Dispatch, PropsWithChildren, SetStateAction } from 'react'
4import {
5 Button,
6 DropdownMenu,
7 DropdownMenuCheckboxItem,
8 DropdownMenuContent,
9 DropdownMenuLabel,
10 DropdownMenuSeparator,
11 DropdownMenuTrigger,
12} from 'ui'
13
14import { PERMISSIONS_DESCRIPTIONS } from '../OAuthApps.constants'
15
16const ScopeDropdownCheckboxItem = ({
17 children,
18 scopeName,
19 scopes,
20 onChange,
21}: PropsWithChildren<{
22 scopeName: OAuthScope
23 scopes: OAuthScope[]
24 onChange: (v: OAuthScope[]) => void
25}>) => {
26 return (
27 <DropdownMenuCheckboxItem
28 checked={scopes.includes(scopeName)}
29 onCheckedChange={(checked) => {
30 if (checked) {
31 onChange([...scopes, scopeName])
32 } else {
33 onChange([...scopes.filter((s) => s !== scopeName)])
34 }
35 }}
36 >
37 {children}
38 </DropdownMenuCheckboxItem>
39 )
40}
41
42const Scope = ({
43 title,
44 description,
45 readScopeName,
46 writeScopeName,
47 scopes,
48 setScopes,
49}: {
50 title: string
51 description: string
52 readScopeName: OAuthScope
53 writeScopeName: OAuthScope
54 scopes: OAuthScope[]
55 setScopes: Dispatch<SetStateAction<OAuthScope[]>>
56}) => {
57 let accessDescription = 'Access: No access'
58 if (scopes.includes(readScopeName)) {
59 accessDescription = 'Access: Read-only'
60 }
61 if (scopes.includes(writeScopeName)) {
62 accessDescription = 'Access: Write-only'
63 }
64 if (scopes.includes(readScopeName) && scopes.includes(writeScopeName)) {
65 accessDescription = 'Access: Read and write'
66 }
67
68 return (
69 <div
70 className="flex flex-row justify-between p-4 border first:rounded-t last:rounded-b gap-x-2"
71 key={title}
72 >
73 <div className="flex flex-col">
74 <span className="text-foreground text-sm">{title}</span>
75 <span className="text-foreground-light text-xs capitalize-sentence">{description}</span>
76 </div>
77 <DropdownMenu>
78 <DropdownMenuTrigger asChild>
79 <Button type="default" iconRight={<ChevronDown />}>
80 <p>{accessDescription}</p>
81 </Button>
82 </DropdownMenuTrigger>
83 <DropdownMenuContent align="end" className="w-40">
84 <DropdownMenuLabel>Select an access level</DropdownMenuLabel>
85 <DropdownMenuSeparator />
86 <ScopeDropdownCheckboxItem scopeName={readScopeName} scopes={scopes} onChange={setScopes}>
87 Read
88 </ScopeDropdownCheckboxItem>
89 <ScopeDropdownCheckboxItem
90 scopeName={writeScopeName}
91 scopes={scopes}
92 onChange={setScopes}
93 >
94 Write
95 </ScopeDropdownCheckboxItem>
96 </DropdownMenuContent>
97 </DropdownMenu>
98 </div>
99 )
100}
101
102export const ScopesPanel = ({
103 scopes,
104 setScopes,
105}: {
106 scopes: OAuthScope[]
107 setScopes: Dispatch<SetStateAction<OAuthScope[]>>
108}) => {
109 return (
110 <div className="-space-y-px">
111 <Scope
112 title="Analytics"
113 description={PERMISSIONS_DESCRIPTIONS.ANALYTICS}
114 readScopeName={OAuthScope.ANALYTICS_READ}
115 writeScopeName={OAuthScope.ANALYTICS_WRITE}
116 scopes={scopes}
117 setScopes={setScopes}
118 />
119 <Scope
120 title="Analytics Config"
121 description={PERMISSIONS_DESCRIPTIONS.ANALYTICS_CONFIG}
122 readScopeName={OAuthScope.ANALYTICS_CONFIG_READ}
123 writeScopeName={OAuthScope.ANALYTICS_CONFIG_WRITE}
124 scopes={scopes}
125 setScopes={setScopes}
126 />
127 <Scope
128 title="Auth"
129 description={PERMISSIONS_DESCRIPTIONS.AUTH}
130 readScopeName={OAuthScope.AUTH_READ}
131 writeScopeName={OAuthScope.AUTH_WRITE}
132 scopes={scopes}
133 setScopes={setScopes}
134 />
135 <Scope
136 title="Database"
137 description={PERMISSIONS_DESCRIPTIONS.DATABASE}
138 readScopeName={OAuthScope.DATABASE_READ}
139 writeScopeName={OAuthScope.DATABASE_WRITE}
140 scopes={scopes}
141 setScopes={setScopes}
142 />
143 <Scope
144 title="Domains"
145 description={PERMISSIONS_DESCRIPTIONS.DOMAINS}
146 readScopeName={OAuthScope.DOMAINS_READ}
147 writeScopeName={OAuthScope.DOMAINS_WRITE}
148 scopes={scopes}
149 setScopes={setScopes}
150 />
151 <Scope
152 title="Edge Functions"
153 description={PERMISSIONS_DESCRIPTIONS.EDGE_FUNCTIONS}
154 readScopeName={OAuthScope.EDGE_FUNCTIONS_READ}
155 writeScopeName={OAuthScope.EDGE_FUNCTIONS_WRITE}
156 scopes={scopes}
157 setScopes={setScopes}
158 />
159 <Scope
160 title="Environment"
161 description={PERMISSIONS_DESCRIPTIONS.ENVIRONMENT}
162 readScopeName={OAuthScope.ENVIRONMENT_READ}
163 writeScopeName={OAuthScope.ENVIRONMENT_WRITE}
164 scopes={scopes}
165 setScopes={setScopes}
166 />
167 <Scope
168 title="Organizations"
169 description={PERMISSIONS_DESCRIPTIONS.ORGANIZATIONS}
170 readScopeName={OAuthScope.ORGANIZATIONS_READ}
171 writeScopeName={OAuthScope.ORGANIZATIONS_WRITE}
172 scopes={scopes}
173 setScopes={setScopes}
174 />
175 <Scope
176 title="Projects"
177 description={PERMISSIONS_DESCRIPTIONS.PROJECTS}
178 readScopeName={OAuthScope.PROJECTS_READ}
179 writeScopeName={OAuthScope.PROJECTS_WRITE}
180 scopes={scopes}
181 setScopes={setScopes}
182 />
183 <Scope
184 title="REST"
185 description={PERMISSIONS_DESCRIPTIONS.REST}
186 readScopeName={OAuthScope.REST_READ}
187 writeScopeName={OAuthScope.REST_WRITE}
188 scopes={scopes}
189 setScopes={setScopes}
190 />
191 <Scope
192 title="Secrets"
193 description={PERMISSIONS_DESCRIPTIONS.SECRETS}
194 readScopeName={OAuthScope.SECRETS_READ}
195 writeScopeName={OAuthScope.SECRETS_WRITE}
196 scopes={scopes}
197 setScopes={setScopes}
198 />
199 <Scope
200 title="Storage"
201 description={PERMISSIONS_DESCRIPTIONS.STORAGE}
202 readScopeName={OAuthScope.STORAGE_READ}
203 writeScopeName={OAuthScope.STORAGE_WRITE}
204 scopes={scopes}
205 setScopes={setScopes}
206 />
207 </div>
208 )
209}