Skip to content

Commit

Permalink
Prevent non owners from editing shared snippets (supabase#30692)
Browse files Browse the repository at this point in the history
* Prevent non owners from editing shared snippets

* Add guard against saving snippet which is shared + has folder id

* FIX
  • Loading branch information
joshenlim authored Nov 27, 2024
1 parent 3e7a0df commit f2d9203
Show file tree
Hide file tree
Showing 2 changed files with 98 additions and 69 deletions.
120 changes: 67 additions & 53 deletions apps/studio/components/interfaces/SQLEditor/MonacoEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,14 @@ import { useLocalStorageQuery } from 'hooks/misc/useLocalStorage'
import { useSelectedProject } from 'hooks/misc/useSelectedProject'
import { LOCAL_STORAGE_KEYS } from 'lib/constants'
import { useProfile } from 'lib/profile'
import { useAppStateSnapshot } from 'state/app-state'
import { useSqlEditorV2StateSnapshot } from 'state/sql-editor-v2'
import { cn } from 'ui'
import { Admonition } from 'ui-patterns'
import { useIsAssistantV2Enabled } from '../App/FeaturePreview/FeaturePreviewContext'
import { untitledSnippetTitle } from './SQLEditor.constants'
import type { IStandaloneCodeEditor } from './SQLEditor.types'
import { createSqlSnippetSkeletonV2 } from './SQLEditor.utils'
import { useIsAssistantV2Enabled } from '../App/FeaturePreview/FeaturePreviewContext'
import { useAppStateSnapshot } from 'state/app-state'

export type MonacoEditorProps = {
id: string
Expand Down Expand Up @@ -50,6 +51,8 @@ const MonacoEditor = ({
)

const snippet = snapV2.snippets[id]
const disableEdit =
snippet?.snippet.visibility === 'project' && snippet?.snippet.owner_id !== profile?.id

const executeQueryRef = useRef(executeQuery)
executeQueryRef.current = executeQuery
Expand Down Expand Up @@ -152,57 +155,68 @@ const MonacoEditor = ({
}, [])

return (
<Editor
className={cn(className, 'monaco-editor')}
theme={'supabase'}
onMount={handleEditorOnMount}
onChange={handleEditorChange}
defaultLanguage="pgsql"
defaultValue={snippet?.snippet.content.sql}
path={id}
options={{
tabSize: 2,
fontSize: 13,
minimap: { enabled: false },
wordWrap: 'on',
// [Joshen] Commenting the following out as it causes the autocomplete suggestion popover
// to be positioned wrongly somehow. I'm not sure if this affects anything though, but leaving
// comment just in case anyone might be wondering. Relevant issues:
// - https://github.com/microsoft/monaco-editor/issues/2229
// - https://github.com/microsoft/monaco-editor/issues/2503
// fixedOverflowWidgets: true,
suggest: {
showMethods: intellisenseEnabled,
showFunctions: intellisenseEnabled,
showConstructors: intellisenseEnabled,
showDeprecated: intellisenseEnabled,
showFields: intellisenseEnabled,
showVariables: intellisenseEnabled,
showClasses: intellisenseEnabled,
showStructs: intellisenseEnabled,
showInterfaces: intellisenseEnabled,
showModules: intellisenseEnabled,
showProperties: intellisenseEnabled,
showEvents: intellisenseEnabled,
showOperators: intellisenseEnabled,
showUnits: intellisenseEnabled,
showValues: intellisenseEnabled,
showConstants: intellisenseEnabled,
showEnums: intellisenseEnabled,
showEnumMembers: intellisenseEnabled,
showKeywords: intellisenseEnabled,
showWords: intellisenseEnabled,
showColors: intellisenseEnabled,
showFiles: intellisenseEnabled,
showReferences: intellisenseEnabled,
showFolders: intellisenseEnabled,
showTypeParameters: intellisenseEnabled,
showIssues: intellisenseEnabled,
showUsers: intellisenseEnabled,
showSnippets: intellisenseEnabled,
},
}}
/>
<>
{disableEdit && (
<Admonition
type="default"
className="m-0 py-2 rounded-none border-0 border-b [&>h5]:mb-0.5"
title="This snippet has been shared to the project and is only editable by the owner who created this snippet"
description='You may duplicate this snippet into a personal copy by right clicking on the snippet and selecting "Duplicate personal copy"'
/>
)}
<Editor
className={cn(className, 'monaco-editor')}
theme={'supabase'}
onMount={handleEditorOnMount}
onChange={handleEditorChange}
defaultLanguage="pgsql"
defaultValue={snippet?.snippet.content.sql}
path={id}
options={{
tabSize: 2,
fontSize: 13,
readOnly: disableEdit,
minimap: { enabled: false },
wordWrap: 'on',
// [Joshen] Commenting the following out as it causes the autocomplete suggestion popover
// to be positioned wrongly somehow. I'm not sure if this affects anything though, but leaving
// comment just in case anyone might be wondering. Relevant issues:
// - https://github.com/microsoft/monaco-editor/issues/2229
// - https://github.com/microsoft/monaco-editor/issues/2503
// fixedOverflowWidgets: true,
suggest: {
showMethods: intellisenseEnabled,
showFunctions: intellisenseEnabled,
showConstructors: intellisenseEnabled,
showDeprecated: intellisenseEnabled,
showFields: intellisenseEnabled,
showVariables: intellisenseEnabled,
showClasses: intellisenseEnabled,
showStructs: intellisenseEnabled,
showInterfaces: intellisenseEnabled,
showModules: intellisenseEnabled,
showProperties: intellisenseEnabled,
showEvents: intellisenseEnabled,
showOperators: intellisenseEnabled,
showUnits: intellisenseEnabled,
showValues: intellisenseEnabled,
showConstants: intellisenseEnabled,
showEnums: intellisenseEnabled,
showEnumMembers: intellisenseEnabled,
showKeywords: intellisenseEnabled,
showWords: intellisenseEnabled,
showColors: intellisenseEnabled,
showFiles: intellisenseEnabled,
showReferences: intellisenseEnabled,
showFolders: intellisenseEnabled,
showTypeParameters: intellisenseEnabled,
showIssues: intellisenseEnabled,
showUsers: intellisenseEnabled,
showSnippets: intellisenseEnabled,
},
}}
/>
</>
)
}

Expand Down
47 changes: 31 additions & 16 deletions apps/studio/state/sql-editor-v2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -462,22 +462,37 @@ if (typeof window !== 'undefined') {
const folder = state.folders[id]

if (snippet) {
debouncedUpdateSnippet(id, snippet.projectRef, {
id,
type: 'sql',
name: snippet.snippet.name ?? 'Untitled',
description: snippet.snippet.description ?? '',
visibility: snippet.snippet.visibility ?? 'user',
project_id: snippet.snippet.project_id ?? 0,
owner_id: snippet.snippet.owner_id,
folder_id: snippet.snippet.folder_id,
content: {
...snippet.snippet.content,
content_id: id,
favorite: snippet.snippet.favorite,
},
})
sqlEditorState.needsSaving.delete(id)
const {
name,
description,
visibility,
project_id,
owner_id,
folder_id,
content,
favorite,
} = snippet.snippet

if (visibility === 'project' && !!folder_id) {
toast.error('Shared snippet cannot be within a folder')
} else {
debouncedUpdateSnippet(id, snippet.projectRef, {
id,
type: 'sql',
name: name ?? 'Untitled',
description: description ?? '',
visibility: visibility ?? 'user',
project_id: project_id ?? 0,
owner_id: owner_id,
folder_id: folder_id,
content: {
...content,
content_id: id,
favorite: favorite,
},
})
sqlEditorState.needsSaving.delete(id)
}
} else if (folder) {
upsertFolder(id, folder.projectRef, folder.folder.name)
sqlEditorState.needsSaving.delete(id)
Expand Down

0 comments on commit f2d9203

Please sign in to comment.