mirror of
https://github.com/AeThex-Corporation/AeThex-OS.git
synced 2026-04-18 06:17:21 +00:00
- ModuleManager: Central tracking for installed marketplace modules - DataAnalyzerWidget: Real-time CPU/RAM/Battery/Storage widget (unlocked by Data Analyzer module) - BottomNavBar: Navigation bar for Projects/Chat/Marketplace/Settings - RootShell: Real root command execution utility - TerminalActivity: Full root shell with neofetch, sysinfo, real Linux commands - Terminal Pro module: Adds aliases (ll, la, h), command history - ArcadeActivity + SnakeGame: Pixel Arcade module unlocks retro games - fade_in/fade_out animations for smooth transitions
202 lines
8 KiB
PL/PgSQL
202 lines
8 KiB
PL/PgSQL
-- Migration 001: Messaging System
|
|
-- Creates tables for conversations, messages, participants, reactions
|
|
|
|
-- ============================================================================
|
|
-- CONVERSATIONS
|
|
-- ============================================================================
|
|
|
|
CREATE TABLE IF NOT EXISTS conversations (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
type VARCHAR(20) NOT NULL CHECK (type IN ('direct', 'group', 'channel')),
|
|
title VARCHAR(200),
|
|
description TEXT,
|
|
avatar_url VARCHAR(500),
|
|
created_by UUID REFERENCES auth.users(id),
|
|
is_archived BOOLEAN DEFAULT false,
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_conversations_type ON conversations(type);
|
|
CREATE INDEX IF NOT EXISTS idx_conversations_creator ON conversations(created_by);
|
|
CREATE INDEX IF NOT EXISTS idx_conversations_updated ON conversations(updated_at DESC);
|
|
|
|
-- ============================================================================
|
|
-- CONVERSATION PARTICIPANTS
|
|
-- ============================================================================
|
|
|
|
CREATE TABLE IF NOT EXISTS conversation_participants (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
conversation_id UUID NOT NULL REFERENCES conversations(id) ON DELETE CASCADE,
|
|
user_id UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
|
|
role VARCHAR(20) DEFAULT 'member' CHECK (role IN ('admin', 'moderator', 'member')),
|
|
joined_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
last_read_at TIMESTAMP WITH TIME ZONE,
|
|
notification_settings JSONB DEFAULT '{"enabled": true, "mentions_only": false}'::jsonb,
|
|
UNIQUE(conversation_id, user_id)
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_participants_conversation ON conversation_participants(conversation_id);
|
|
CREATE INDEX IF NOT EXISTS idx_participants_user ON conversation_participants(user_id);
|
|
|
|
-- ============================================================================
|
|
-- MESSAGES
|
|
-- ============================================================================
|
|
|
|
CREATE TABLE IF NOT EXISTS messages (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
conversation_id UUID NOT NULL REFERENCES conversations(id) ON DELETE CASCADE,
|
|
sender_id UUID NOT NULL REFERENCES auth.users(id),
|
|
content TEXT NOT NULL,
|
|
content_type VARCHAR(20) DEFAULT 'text' CHECK (content_type IN ('text', 'image', 'video', 'audio', 'file', 'code')),
|
|
metadata JSONB,
|
|
reply_to_id UUID REFERENCES messages(id) ON DELETE SET NULL,
|
|
edited_at TIMESTAMP WITH TIME ZONE,
|
|
deleted_at TIMESTAMP WITH TIME ZONE,
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_messages_conversation ON messages(conversation_id, created_at DESC);
|
|
CREATE INDEX IF NOT EXISTS idx_messages_sender ON messages(sender_id);
|
|
CREATE INDEX IF NOT EXISTS idx_messages_reply_to ON messages(reply_to_id);
|
|
CREATE INDEX IF NOT EXISTS idx_messages_created ON messages(created_at DESC);
|
|
|
|
-- ============================================================================
|
|
-- MESSAGE REACTIONS
|
|
-- ============================================================================
|
|
|
|
CREATE TABLE IF NOT EXISTS message_reactions (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
message_id UUID NOT NULL REFERENCES messages(id) ON DELETE CASCADE,
|
|
user_id UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
|
|
emoji VARCHAR(20) NOT NULL,
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
UNIQUE(message_id, user_id, emoji)
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_reactions_message ON message_reactions(message_id);
|
|
CREATE INDEX IF NOT EXISTS idx_reactions_user ON message_reactions(user_id);
|
|
|
|
-- ============================================================================
|
|
-- MESSAGE ATTACHMENTS
|
|
-- ============================================================================
|
|
|
|
CREATE TABLE IF NOT EXISTS message_attachments (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
message_id UUID NOT NULL REFERENCES messages(id) ON DELETE CASCADE,
|
|
file_name VARCHAR(500) NOT NULL,
|
|
file_url VARCHAR(1000) NOT NULL,
|
|
file_size INTEGER,
|
|
file_type VARCHAR(100),
|
|
uploaded_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_attachments_message ON message_attachments(message_id);
|
|
|
|
-- ============================================================================
|
|
-- FUNCTIONS
|
|
-- ============================================================================
|
|
|
|
-- Function to update conversation updated_at timestamp when messages are added
|
|
CREATE OR REPLACE FUNCTION update_conversation_timestamp()
|
|
RETURNS TRIGGER AS $$
|
|
BEGIN
|
|
UPDATE conversations
|
|
SET updated_at = NOW()
|
|
WHERE id = NEW.conversation_id;
|
|
RETURN NEW;
|
|
END;
|
|
$$ LANGUAGE plpgsql;
|
|
|
|
-- Trigger to update conversation timestamp on new message
|
|
DROP TRIGGER IF EXISTS trigger_update_conversation_timestamp ON messages;
|
|
CREATE TRIGGER trigger_update_conversation_timestamp
|
|
AFTER INSERT ON messages
|
|
FOR EACH ROW
|
|
EXECUTE FUNCTION update_conversation_timestamp();
|
|
|
|
-- Function to get or create a direct conversation between two users
|
|
CREATE OR REPLACE FUNCTION get_or_create_direct_conversation(user1_id UUID, user2_id UUID)
|
|
RETURNS UUID AS $$
|
|
DECLARE
|
|
conv_id UUID;
|
|
BEGIN
|
|
-- Check if direct conversation exists between these two users
|
|
SELECT c.id INTO conv_id
|
|
FROM conversations c
|
|
WHERE c.type = 'direct'
|
|
AND EXISTS (SELECT 1 FROM conversation_participants WHERE conversation_id = c.id AND user_id = user1_id)
|
|
AND EXISTS (SELECT 1 FROM conversation_participants WHERE conversation_id = c.id AND user_id = user2_id)
|
|
AND (SELECT COUNT(*) FROM conversation_participants WHERE conversation_id = c.id) = 2
|
|
LIMIT 1;
|
|
|
|
-- If not found, create new conversation
|
|
IF conv_id IS NULL THEN
|
|
INSERT INTO conversations (type, created_by)
|
|
VALUES ('direct', user1_id)
|
|
RETURNING id INTO conv_id;
|
|
|
|
-- Add both participants
|
|
INSERT INTO conversation_participants (conversation_id, user_id, role)
|
|
VALUES (conv_id, user1_id, 'member'), (conv_id, user2_id, 'member');
|
|
END IF;
|
|
|
|
RETURN conv_id;
|
|
END;
|
|
$$ LANGUAGE plpgsql;
|
|
|
|
-- ============================================================================
|
|
-- ROW LEVEL SECURITY
|
|
-- ============================================================================
|
|
|
|
ALTER TABLE conversations ENABLE ROW LEVEL SECURITY;
|
|
ALTER TABLE conversation_participants ENABLE ROW LEVEL SECURITY;
|
|
ALTER TABLE messages ENABLE ROW LEVEL SECURITY;
|
|
ALTER TABLE message_reactions ENABLE ROW LEVEL SECURITY;
|
|
ALTER TABLE message_attachments ENABLE ROW LEVEL SECURITY;
|
|
|
|
-- Conversations: Users can see conversations they're participants in
|
|
CREATE POLICY "Users can view their conversations" ON conversations
|
|
FOR SELECT USING (
|
|
EXISTS (
|
|
SELECT 1 FROM conversation_participants
|
|
WHERE conversation_id = id AND user_id = auth.uid()
|
|
)
|
|
);
|
|
|
|
CREATE POLICY "Users can create conversations" ON conversations
|
|
FOR INSERT WITH CHECK (created_by = auth.uid());
|
|
|
|
-- Participants: Users can see participants in their conversations
|
|
CREATE POLICY "Users can view participants in their conversations" ON conversation_participants
|
|
FOR SELECT USING (
|
|
EXISTS (
|
|
SELECT 1 FROM conversation_participants cp
|
|
WHERE cp.conversation_id = conversation_participants.conversation_id
|
|
AND cp.user_id = auth.uid()
|
|
)
|
|
);
|
|
|
|
-- Messages: Users can see messages in conversations they're in
|
|
CREATE POLICY "Users can view messages in their conversations" ON messages
|
|
FOR SELECT USING (
|
|
EXISTS (
|
|
SELECT 1 FROM conversation_participants
|
|
WHERE conversation_id = messages.conversation_id AND user_id = auth.uid()
|
|
)
|
|
);
|
|
|
|
CREATE POLICY "Users can send messages to their conversations" ON messages
|
|
FOR INSERT WITH CHECK (
|
|
sender_id = auth.uid() AND
|
|
EXISTS (
|
|
SELECT 1 FROM conversation_participants
|
|
WHERE conversation_id = messages.conversation_id AND user_id = auth.uid()
|
|
)
|
|
);
|
|
|
|
CREATE POLICY "Users can edit their own messages" ON messages
|
|
FOR UPDATE USING (sender_id = auth.uid());
|
|
|
|
CREATE POLICY "Users can delete their own messages" ON messages
|
|
FOR DELETE USING (sender_id = auth.uid());
|