BetterBase provides Row Level Security for fine-grained access control at the database level.
RLS ensures users can only access data they're authorized to see. Policies are enforced at the database level, providing security even if application-level checks are bypassed.
Enable RLS on tables:
# Enable RLS for a table
bb rls enable --table users
# Disable RLS for a table
bb rls disable --table users# Create a policy
bb rls create \
--table posts \
--name users-own-posts \
--command SELECT \
--check "user_id = auth.uid()"// PostgreSQL policy
CREATE POLICY "users-own-posts" ON posts
FOR SELECT
USING (user_id = auth.uid());
CREATE POLICY "users-own-posts" ON posts
FOR INSERT
WITH CHECK (user_id = auth.uid());
CREATE POLICY "users-own-posts" ON posts
FOR UPDATE
USING (user_id = auth.uid())
WITH CHECK (user_id = auth.uid());
CREATE POLICY "users-own-posts" ON posts
FOR DELETE
USING (user_id = auth.uid());| Command | Description |
|---|---|
SELECT |
Control read access |
INSERT |
Control new record creation |
UPDATE |
Control record updates |
DELETE |
Control record deletion |
ALL |
All operations |
Available in policy expressions:
| Variable | Description |
|---|---|
auth.uid() |
Current user ID |
auth.role() |
User role (admin, user) |
auth.email() |
User email |
auth.jwt() |
Full JWT claims |
-- Users can only see their own posts
CREATE POLICY "users-own-posts" ON posts
FOR SELECT
USING (user_id = auth.uid());-- Anyone can read published posts
CREATE POLICY "public-posts" ON posts
FOR SELECT
USING (published = true);-- Admins can see all users
CREATE POLICY "admins-see-all" ON users
FOR SELECT
USING (auth.role() = 'admin');-- Users can only see their team's data
CREATE POLICY "team-access" ON documents
FOR SELECT
USING (team_id IN (
SELECT team_id FROM team_members WHERE user_id = auth.uid()
));// With RLS, these queries are automatically filtered
const posts = await client
.from('posts')
.select()
// RLS adds: WHERE user_id = auth.uid()# RLS automatically filters results
query {
posts {
id
title
# Only returns posts user owns
}
}export default async function handler(event) {
// RLS automatically applies
const posts = await db.select().from(posts)
// Returns only user's posts
}# Test RLS policies
bb rls test --table posts
# Test with specific user
bb rls test --table posts --user-id user-123// betterbase.config.ts
export default defineConfig({
rls: {
enabled: true,
auditLog: true
}
})With audit logging, all policy evaluations are logged.
- Enable RLS on all tables - Start with RLS enabled
- Use specific policies - Don't use overly permissive policies
- Test policies - Verify policies work as expected
- Audit logs - Enable logging for production
- Separate read/write policies - Fine-tune separately
Add RLS during migrations:
# Add policy in migration
bb migrate generate add-rls-policies# List all policies
bb rls list
# Check policy status
bb rls status --table users- Database - Schema and tables
- Authentication - User authentication
- CLI Commands - RLS CLI