AuthorizeRequesterDetails.tsx160 lines · main
| 1 | import { OAuthScope } from '@supabase/shared-types/out/constants' |
| 2 | import { Check } from 'lucide-react' |
| 3 | |
| 4 | import { PERMISSIONS_DESCRIPTIONS } from './OAuthApps.constants' |
| 5 | |
| 6 | export interface AuthorizeRequesterDetailsProps { |
| 7 | icon: string | null |
| 8 | name: string |
| 9 | domain: string |
| 10 | scopes: OAuthScope[] |
| 11 | showOnlyScopes?: boolean |
| 12 | } |
| 13 | |
| 14 | export const ScopeSection = ({ |
| 15 | description, |
| 16 | hasReadScope, |
| 17 | hasWriteScope, |
| 18 | }: { |
| 19 | description: string |
| 20 | hasReadScope: boolean |
| 21 | hasWriteScope: boolean |
| 22 | }) => { |
| 23 | if (hasReadScope || hasWriteScope) { |
| 24 | const perms = [hasReadScope ? 'Read' : null, hasWriteScope ? 'Write' : null] |
| 25 | .filter(Boolean) |
| 26 | |
| 27 | .map((str) => ( |
| 28 | <span key={str} className="font-semibold text-foreground"> |
| 29 | {str} |
| 30 | </span> |
| 31 | )) |
| 32 | .reduce((acc, v) => ( |
| 33 | <> |
| 34 | {acc} |
| 35 | <span> and </span> |
| 36 | {v} |
| 37 | </> |
| 38 | )) |
| 39 | |
| 40 | return ( |
| 41 | <div className="first:border-t border-b flex flex-row space-x-1 text-sm text-foreground-light py-2 px-1"> |
| 42 | <div className="pt-0.5"> |
| 43 | <Check stroke="green" height={18} width={18} strokeWidth={1.5} /> |
| 44 | </div> |
| 45 | <div> |
| 46 | {perms} {description} |
| 47 | </div> |
| 48 | </div> |
| 49 | ) |
| 50 | } |
| 51 | return null |
| 52 | } |
| 53 | |
| 54 | export const AuthorizeRequesterDetails = ({ |
| 55 | icon, |
| 56 | name, |
| 57 | domain, |
| 58 | scopes, |
| 59 | showOnlyScopes = false, |
| 60 | }: AuthorizeRequesterDetailsProps) => { |
| 61 | return ( |
| 62 | <div className="flex gap-y-4 flex-col"> |
| 63 | {!showOnlyScopes && ( |
| 64 | <div className="flex flex-row gap-x-4 items-center"> |
| 65 | <div className="flex items-center"> |
| 66 | <div |
| 67 | className="w-12 h-12 md:w-14 md:h-14 bg-center bg-no-repeat bg-cover flex items-center justify-center rounded-md border border-control" |
| 68 | style={{ |
| 69 | backgroundImage: !!icon ? `url('${icon}')` : 'none', |
| 70 | }} |
| 71 | > |
| 72 | {!icon && <p className="text-foreground-light text-lg">{name[0]}</p>} |
| 73 | </div> |
| 74 | </div> |
| 75 | <p className="text-foreground"> |
| 76 | {name} ({domain}) is requesting API access to an organization. |
| 77 | </p> |
| 78 | </div> |
| 79 | )} |
| 80 | <div> |
| 81 | {!showOnlyScopes && ( |
| 82 | <> |
| 83 | <h3>Permissions</h3> |
| 84 | <p className="text-sm text-foreground-light"> |
| 85 | The following scopes will apply for the{' '} |
| 86 | <span className="text-amber-900">selected organization and all of its projects.</span> |
| 87 | </p> |
| 88 | </> |
| 89 | )} |
| 90 | <div className="pt-2"> |
| 91 | {scopes.length === 0 && ( |
| 92 | <p className="text-foreground-lighter text-sm"> |
| 93 | No permissions requested, {name} will not have access to your organization or projects |
| 94 | </p> |
| 95 | )} |
| 96 | <ScopeSection |
| 97 | description={PERMISSIONS_DESCRIPTIONS.ANALYTICS} |
| 98 | hasReadScope={scopes.includes(OAuthScope.ANALYTICS_READ)} |
| 99 | hasWriteScope={scopes.includes(OAuthScope.ANALYTICS_WRITE)} |
| 100 | /> |
| 101 | <ScopeSection |
| 102 | description={PERMISSIONS_DESCRIPTIONS.ANALYTICS_CONFIG} |
| 103 | hasReadScope={scopes.includes(OAuthScope.ANALYTICS_CONFIG_READ)} |
| 104 | hasWriteScope={scopes.includes(OAuthScope.ANALYTICS_CONFIG_WRITE)} |
| 105 | /> |
| 106 | <ScopeSection |
| 107 | description={PERMISSIONS_DESCRIPTIONS.AUTH} |
| 108 | hasReadScope={scopes.includes(OAuthScope.AUTH_READ)} |
| 109 | hasWriteScope={scopes.includes(OAuthScope.AUTH_WRITE)} |
| 110 | /> |
| 111 | <ScopeSection |
| 112 | description={PERMISSIONS_DESCRIPTIONS.DATABASE} |
| 113 | hasReadScope={scopes.includes(OAuthScope.DATABASE_READ)} |
| 114 | hasWriteScope={scopes.includes(OAuthScope.DATABASE_WRITE)} |
| 115 | /> |
| 116 | <ScopeSection |
| 117 | description={PERMISSIONS_DESCRIPTIONS.DOMAINS} |
| 118 | hasReadScope={scopes.includes(OAuthScope.DOMAINS_READ)} |
| 119 | hasWriteScope={scopes.includes(OAuthScope.DOMAINS_WRITE)} |
| 120 | /> |
| 121 | <ScopeSection |
| 122 | description={PERMISSIONS_DESCRIPTIONS.EDGE_FUNCTIONS} |
| 123 | hasReadScope={scopes.includes(OAuthScope.EDGE_FUNCTIONS_READ)} |
| 124 | hasWriteScope={scopes.includes(OAuthScope.EDGE_FUNCTIONS_WRITE)} |
| 125 | /> |
| 126 | <ScopeSection |
| 127 | description={PERMISSIONS_DESCRIPTIONS.ENVIRONMENT} |
| 128 | hasReadScope={scopes.includes(OAuthScope.ENVIRONMENT_READ)} |
| 129 | hasWriteScope={scopes.includes(OAuthScope.ENVIRONMENT_WRITE)} |
| 130 | /> |
| 131 | <ScopeSection |
| 132 | description={PERMISSIONS_DESCRIPTIONS.ORGANIZATIONS} |
| 133 | hasReadScope={scopes.includes(OAuthScope.ORGANIZATIONS_READ)} |
| 134 | hasWriteScope={scopes.includes(OAuthScope.ORGANIZATIONS_WRITE)} |
| 135 | /> |
| 136 | <ScopeSection |
| 137 | description={PERMISSIONS_DESCRIPTIONS.PROJECTS} |
| 138 | hasReadScope={scopes.includes(OAuthScope.PROJECTS_READ)} |
| 139 | hasWriteScope={scopes.includes(OAuthScope.PROJECTS_WRITE)} |
| 140 | /> |
| 141 | <ScopeSection |
| 142 | description={PERMISSIONS_DESCRIPTIONS.REST} |
| 143 | hasReadScope={scopes.includes(OAuthScope.REST_READ)} |
| 144 | hasWriteScope={scopes.includes(OAuthScope.REST_WRITE)} |
| 145 | /> |
| 146 | <ScopeSection |
| 147 | description={PERMISSIONS_DESCRIPTIONS.SECRETS} |
| 148 | hasReadScope={scopes.includes(OAuthScope.SECRETS_READ)} |
| 149 | hasWriteScope={scopes.includes(OAuthScope.SECRETS_WRITE)} |
| 150 | /> |
| 151 | <ScopeSection |
| 152 | description={PERMISSIONS_DESCRIPTIONS.STORAGE} |
| 153 | hasReadScope={scopes.includes(OAuthScope.STORAGE_READ)} |
| 154 | hasWriteScope={scopes.includes(OAuthScope.STORAGE_WRITE)} |
| 155 | /> |
| 156 | </div> |
| 157 | </div> |
| 158 | </div> |
| 159 | ) |
| 160 | } |