165 lines
6.3 KiB
MySQL
165 lines
6.3 KiB
MySQL
|
|
-- Create shared_notes table for public sharing functionality
|
||
|
|
CREATE TABLE IF NOT EXISTS shared_notes (
|
||
|
|
note_id TEXT PRIMARY KEY,
|
||
|
|
user_id UUID NOT NULL,
|
||
|
|
is_public BOOLEAN DEFAULT FALSE,
|
||
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
||
|
|
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
||
|
|
|
||
|
|
-- Foreign key constraint to notes table
|
||
|
|
CONSTRAINT fk_shared_notes_note_id
|
||
|
|
FOREIGN KEY (note_id) REFERENCES notes(id) ON DELETE CASCADE,
|
||
|
|
|
||
|
|
-- Foreign key constraint to users table (auth.users)
|
||
|
|
CONSTRAINT fk_shared_notes_user_id
|
||
|
|
FOREIGN KEY (user_id) REFERENCES auth.users(id) ON DELETE CASCADE
|
||
|
|
);
|
||
|
|
|
||
|
|
-- Create index for performance on public notes
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_shared_notes_is_public ON shared_notes(is_public);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_shared_notes_user_id ON shared_notes(user_id);
|
||
|
|
|
||
|
|
-- Enable Row Level Security
|
||
|
|
ALTER TABLE shared_notes ENABLE ROW LEVEL SECURITY;
|
||
|
|
|
||
|
|
-- Policy to allow users to view their own shared_notes entries
|
||
|
|
CREATE POLICY "Users can view their own shared notes" ON shared_notes
|
||
|
|
FOR SELECT
|
||
|
|
TO authenticated
|
||
|
|
USING (user_id = (SELECT auth.uid()));
|
||
|
|
|
||
|
|
-- Policy to allow anonymous users to view public notes
|
||
|
|
CREATE POLICY "Anyone can view public notes" ON shared_notes
|
||
|
|
FOR SELECT
|
||
|
|
TO anon
|
||
|
|
USING (is_public = TRUE);
|
||
|
|
|
||
|
|
-- Policy to allow users to insert their own shared_notes entries
|
||
|
|
CREATE POLICY "Users can insert their own shared notes" ON shared_notes
|
||
|
|
FOR INSERT
|
||
|
|
TO authenticated
|
||
|
|
WITH CHECK (user_id = (SELECT auth.uid()));
|
||
|
|
|
||
|
|
-- Policy to allow users to update their own shared_notes entries
|
||
|
|
CREATE POLICY "Users can update their own shared notes" ON shared_notes
|
||
|
|
FOR UPDATE
|
||
|
|
TO authenticated
|
||
|
|
USING (user_id = (SELECT auth.uid()))
|
||
|
|
WITH CHECK (user_id = (SELECT auth.uid()));
|
||
|
|
|
||
|
|
-- Policy to allow users to delete their own shared_notes entries
|
||
|
|
CREATE POLICY "Users can delete their own shared notes" ON shared_notes
|
||
|
|
FOR DELETE
|
||
|
|
TO authenticated
|
||
|
|
USING (user_id = (SELECT auth.uid()));
|
||
|
|
|
||
|
|
-- Create note_access table for tablo-based sharing
|
||
|
|
CREATE TABLE IF NOT EXISTS note_access (
|
||
|
|
id SERIAL PRIMARY KEY,
|
||
|
|
note_id TEXT NOT NULL,
|
||
|
|
user_id UUID NOT NULL,
|
||
|
|
tablo_id TEXT,
|
||
|
|
is_active BOOLEAN DEFAULT TRUE,
|
||
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
||
|
|
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
||
|
|
|
||
|
|
-- Foreign key constraint to notes table
|
||
|
|
CONSTRAINT fk_note_access_note_id
|
||
|
|
FOREIGN KEY (note_id) REFERENCES notes(id) ON DELETE CASCADE,
|
||
|
|
|
||
|
|
-- Foreign key constraint to users table (auth.users)
|
||
|
|
CONSTRAINT fk_note_access_user_id
|
||
|
|
FOREIGN KEY (user_id) REFERENCES auth.users(id) ON DELETE CASCADE,
|
||
|
|
|
||
|
|
-- Foreign key constraint to tablos table (nullable for "all tablos" sharing)
|
||
|
|
CONSTRAINT fk_note_access_tablo_id
|
||
|
|
FOREIGN KEY (tablo_id) REFERENCES tablos(id) ON DELETE CASCADE
|
||
|
|
);
|
||
|
|
|
||
|
|
-- Create indexes for performance
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_note_access_note_id ON note_access(note_id);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_note_access_user_id ON note_access(user_id);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_note_access_tablo_id ON note_access(tablo_id);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_note_access_is_active ON note_access(is_active);
|
||
|
|
|
||
|
|
-- Unique constraint for specific tablo sharing (when tablo_id IS NOT NULL)
|
||
|
|
CREATE UNIQUE INDEX IF NOT EXISTS unique_note_access_with_tablo
|
||
|
|
ON note_access(note_id, user_id, tablo_id)
|
||
|
|
WHERE tablo_id IS NOT NULL;
|
||
|
|
|
||
|
|
-- Unique constraint for "all tablos" sharing (when tablo_id IS NULL)
|
||
|
|
-- Only one NULL tablo_id per (note_id, user_id) combination
|
||
|
|
CREATE UNIQUE INDEX IF NOT EXISTS unique_note_access_all_tablos
|
||
|
|
ON note_access(note_id, user_id)
|
||
|
|
WHERE tablo_id IS NULL;
|
||
|
|
|
||
|
|
-- Enable Row Level Security
|
||
|
|
ALTER TABLE note_access ENABLE ROW LEVEL SECURITY;
|
||
|
|
|
||
|
|
-- Policy to allow users to view their own note_access entries
|
||
|
|
CREATE POLICY "Users can view their own note access" ON note_access
|
||
|
|
FOR SELECT
|
||
|
|
TO authenticated
|
||
|
|
USING (user_id = (SELECT auth.uid()));
|
||
|
|
|
||
|
|
-- Policy to allow users to view notes shared with their tablos
|
||
|
|
CREATE POLICY "Users can view notes shared with their tablos" ON note_access
|
||
|
|
FOR SELECT
|
||
|
|
TO authenticated
|
||
|
|
USING (
|
||
|
|
is_active = TRUE
|
||
|
|
AND (
|
||
|
|
-- Shared with all tablos (tablo_id is NULL)
|
||
|
|
tablo_id IS NULL
|
||
|
|
-- Or shared with a specific tablo where the user has access
|
||
|
|
OR EXISTS (
|
||
|
|
SELECT 1 FROM tablo_access
|
||
|
|
WHERE tablo_access.tablo_id = note_access.tablo_id
|
||
|
|
AND tablo_access.user_id = (SELECT auth.uid())
|
||
|
|
AND tablo_access.is_active = TRUE
|
||
|
|
)
|
||
|
|
)
|
||
|
|
);
|
||
|
|
|
||
|
|
-- Policy to allow users to insert their own note_access entries
|
||
|
|
CREATE POLICY "Users can insert their own note access" ON note_access
|
||
|
|
FOR INSERT
|
||
|
|
TO authenticated
|
||
|
|
WITH CHECK (user_id = (SELECT auth.uid()));
|
||
|
|
|
||
|
|
-- Policy to allow users to update their own note_access entries
|
||
|
|
CREATE POLICY "Users can update their own note access" ON note_access
|
||
|
|
FOR UPDATE
|
||
|
|
TO authenticated
|
||
|
|
USING (user_id = (SELECT auth.uid()))
|
||
|
|
WITH CHECK (user_id = (SELECT auth.uid()));
|
||
|
|
|
||
|
|
-- Policy to allow users to delete their own note_access entries
|
||
|
|
CREATE POLICY "Users can delete their own note access" ON note_access
|
||
|
|
FOR DELETE
|
||
|
|
TO authenticated
|
||
|
|
USING (user_id = (SELECT auth.uid()));
|
||
|
|
|
||
|
|
-- Add comments to document the tables
|
||
|
|
COMMENT ON TABLE shared_notes IS
|
||
|
|
'Tracks which notes are shared publicly with Row Level Security';
|
||
|
|
|
||
|
|
COMMENT ON COLUMN shared_notes.note_id IS
|
||
|
|
'Foreign key reference to notes.id';
|
||
|
|
|
||
|
|
COMMENT ON COLUMN shared_notes.user_id IS
|
||
|
|
'Foreign key reference to auth.users.id - owner of the note';
|
||
|
|
|
||
|
|
COMMENT ON COLUMN shared_notes.is_public IS
|
||
|
|
'When TRUE, the note is publicly accessible via /notes/public/:noteId';
|
||
|
|
|
||
|
|
COMMENT ON TABLE note_access IS
|
||
|
|
'Tracks which notes are shared with tablos. When tablo_id IS NULL and is_active = TRUE, the note is shared with all user tablos. Uses partial unique indexes to handle NULL values correctly.';
|
||
|
|
|
||
|
|
COMMENT ON COLUMN note_access.tablo_id IS
|
||
|
|
'Foreign key reference to tablos.id - NULL means shared with all user tablos. Partial unique indexes ensure only one NULL per (note_id, user_id) combination.';
|
||
|
|
|
||
|
|
COMMENT ON COLUMN note_access.is_active IS
|
||
|
|
'When TRUE, the sharing is active';
|
||
|
|
|