Implemented: - Database schema (SQLite) with tables: users, profiles, posts, swipes, matches, chats, chat_messages, events, notifications, relationships, post_likes, post_comments, refresh_tokens, media - Core PHP structure following skeleton pattern (www/api/) - JWT Authentication (register, login, refresh, logout) - User profile CRUD (show, update, delete, search) - User sub-resources (posts, friends, followers, following) - Minimal Firebase JWT implementation for PHP without Composer
250 lines
7.9 KiB
SQL
250 lines
7.9 KiB
SQL
-- Sozial Platform Database Schema
|
|
-- SQLite
|
|
|
|
-- Users table
|
|
CREATE TABLE IF NOT EXISTS users (
|
|
id TEXT PRIMARY KEY,
|
|
email TEXT UNIQUE NOT NULL,
|
|
password_hash TEXT NOT NULL,
|
|
username TEXT UNIQUE NOT NULL,
|
|
display_name TEXT,
|
|
bio TEXT,
|
|
avatar_url TEXT,
|
|
photos TEXT, -- JSON array
|
|
gender TEXT,
|
|
interested_in TEXT, -- JSON array
|
|
age INTEGER,
|
|
location TEXT, -- JSON object {city, lat, lng}
|
|
interests TEXT, -- JSON array
|
|
is_online INTEGER DEFAULT 0,
|
|
last_seen INTEGER,
|
|
settings TEXT, -- JSON object
|
|
created_at INTEGER NOT NULL,
|
|
updated_at INTEGER NOT NULL
|
|
);
|
|
|
|
-- Profiles table (extended profile data)
|
|
CREATE TABLE IF NOT EXISTS profiles (
|
|
id TEXT PRIMARY KEY,
|
|
user_id TEXT NOT NULL UNIQUE,
|
|
first_name TEXT,
|
|
last_name TEXT,
|
|
birthday TEXT,
|
|
city TEXT,
|
|
country TEXT,
|
|
latitude REAL,
|
|
longitude REAL,
|
|
height_cm INTEGER,
|
|
body_type TEXT,
|
|
education TEXT,
|
|
occupation TEXT,
|
|
relationship_status TEXT,
|
|
looking_for TEXT,
|
|
about_me TEXT,
|
|
created_at INTEGER NOT NULL,
|
|
updated_at INTEGER NOT NULL,
|
|
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
|
|
);
|
|
|
|
-- Posts table
|
|
CREATE TABLE IF NOT EXISTS posts (
|
|
id TEXT PRIMARY KEY,
|
|
user_id TEXT NOT NULL,
|
|
type TEXT NOT NULL DEFAULT 'text', -- text|image|checkin
|
|
content TEXT,
|
|
media_urls TEXT, -- JSON array
|
|
location TEXT, -- JSON object {name, lat, lng}
|
|
likes_count INTEGER DEFAULT 0,
|
|
comments_count INTEGER DEFAULT 0,
|
|
shares_count INTEGER DEFAULT 0,
|
|
created_at INTEGER NOT NULL,
|
|
updated_at INTEGER NOT NULL,
|
|
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
|
|
);
|
|
|
|
-- Post likes table
|
|
CREATE TABLE IF NOT EXISTS post_likes (
|
|
id TEXT PRIMARY KEY,
|
|
post_id TEXT NOT NULL,
|
|
user_id TEXT NOT NULL,
|
|
created_at INTEGER NOT NULL,
|
|
FOREIGN KEY (post_id) REFERENCES posts(id) ON DELETE CASCADE,
|
|
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
|
|
UNIQUE(post_id, user_id)
|
|
);
|
|
|
|
-- Post comments table
|
|
CREATE TABLE IF NOT EXISTS post_comments (
|
|
id TEXT PRIMARY KEY,
|
|
post_id TEXT NOT NULL,
|
|
user_id TEXT NOT NULL,
|
|
parent_id TEXT,
|
|
content TEXT NOT NULL,
|
|
created_at INTEGER NOT NULL,
|
|
updated_at INTEGER NOT NULL,
|
|
FOREIGN KEY (post_id) REFERENCES posts(id) ON DELETE CASCADE,
|
|
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
|
|
FOREIGN KEY (parent_id) REFERENCES post_comments(id) ON DELETE CASCADE
|
|
);
|
|
|
|
-- Relationships table (follows and friends)
|
|
CREATE TABLE IF NOT EXISTS relationships (
|
|
id TEXT PRIMARY KEY,
|
|
follower_id TEXT NOT NULL,
|
|
following_id TEXT NOT NULL,
|
|
type TEXT NOT NULL DEFAULT 'follow', -- follow|friend
|
|
status TEXT DEFAULT 'active', -- active|blocked|pending
|
|
created_at INTEGER NOT NULL,
|
|
updated_at INTEGER NOT NULL,
|
|
FOREIGN KEY (follower_id) REFERENCES users(id) ON DELETE CASCADE,
|
|
FOREIGN KEY (following_id) REFERENCES users(id) ON DELETE CASCADE,
|
|
UNIQUE(follower_id, following_id)
|
|
);
|
|
|
|
-- Swipes table (for discovery feature)
|
|
CREATE TABLE IF NOT EXISTS swipes (
|
|
id TEXT PRIMARY KEY,
|
|
user_id TEXT NOT NULL,
|
|
target_user_id TEXT NOT NULL,
|
|
direction TEXT NOT NULL, -- like|pass|super_like
|
|
created_at INTEGER NOT NULL,
|
|
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
|
|
FOREIGN KEY (target_user_id) REFERENCES users(id) ON DELETE CASCADE,
|
|
UNIQUE(user_id, target_user_id)
|
|
);
|
|
|
|
-- Matches table
|
|
CREATE TABLE IF NOT EXISTS matches (
|
|
id TEXT PRIMARY KEY,
|
|
user1_id TEXT NOT NULL,
|
|
user2_id TEXT NOT NULL,
|
|
created_at INTEGER NOT NULL,
|
|
FOREIGN KEY (user1_id) REFERENCES users(id) ON DELETE CASCADE,
|
|
FOREIGN KEY (user2_id) REFERENCES users(id) ON DELETE CASCADE,
|
|
UNIQUE(user1_id, user2_id)
|
|
);
|
|
|
|
-- Chats (conversations) table
|
|
CREATE TABLE IF NOT EXISTS chats (
|
|
id TEXT PRIMARY KEY,
|
|
type TEXT NOT NULL DEFAULT 'direct', -- direct|group
|
|
name TEXT,
|
|
avatar_url TEXT,
|
|
created_by TEXT,
|
|
created_at INTEGER NOT NULL,
|
|
updated_at INTEGER NOT NULL,
|
|
FOREIGN KEY (created_by) REFERENCES users(id) ON DELETE SET NULL
|
|
);
|
|
|
|
-- Chat participants table
|
|
CREATE TABLE IF NOT EXISTS chat_participants (
|
|
id TEXT PRIMARY KEY,
|
|
chat_id TEXT NOT NULL,
|
|
user_id TEXT NOT NULL,
|
|
joined_at INTEGER NOT NULL,
|
|
last_read_at INTEGER,
|
|
is_admin INTEGER DEFAULT 0,
|
|
FOREIGN KEY (chat_id) REFERENCES chats(id) ON DELETE CASCADE,
|
|
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
|
|
UNIQUE(chat_id, user_id)
|
|
);
|
|
|
|
-- Chat messages table
|
|
CREATE TABLE IF NOT EXISTS chat_messages (
|
|
id TEXT PRIMARY KEY,
|
|
chat_id TEXT NOT NULL,
|
|
sender_id TEXT NOT NULL,
|
|
content TEXT NOT NULL,
|
|
type TEXT DEFAULT 'text', -- text|image|system
|
|
media_url TEXT,
|
|
read_at INTEGER,
|
|
created_at INTEGER NOT NULL,
|
|
updated_at INTEGER NOT NULL,
|
|
FOREIGN KEY (chat_id) REFERENCES chats(id) ON DELETE CASCADE,
|
|
FOREIGN KEY (sender_id) REFERENCES users(id) ON DELETE CASCADE
|
|
);
|
|
|
|
-- Events table
|
|
CREATE TABLE IF NOT EXISTS events (
|
|
id TEXT PRIMARY KEY,
|
|
creator_id TEXT NOT NULL,
|
|
title TEXT NOT NULL,
|
|
description TEXT,
|
|
event_type TEXT DEFAULT 'meetup', -- meetup|party|date|other
|
|
location_name TEXT,
|
|
location_address TEXT,
|
|
latitude REAL,
|
|
longitude REAL,
|
|
start_date INTEGER,
|
|
end_date INTEGER,
|
|
max_participants INTEGER,
|
|
is_public INTEGER DEFAULT 1,
|
|
created_at INTEGER NOT NULL,
|
|
updated_at INTEGER NOT NULL,
|
|
FOREIGN KEY (creator_id) REFERENCES users(id) ON DELETE CASCADE
|
|
);
|
|
|
|
-- Event participants table
|
|
CREATE TABLE IF NOT EXISTS event_participants (
|
|
id TEXT PRIMARY KEY,
|
|
event_id TEXT NOT NULL,
|
|
user_id TEXT NOT NULL,
|
|
status TEXT DEFAULT 'going', -- going|maybe|not_going
|
|
created_at INTEGER NOT NULL,
|
|
FOREIGN KEY (event_id) REFERENCES events(id) ON DELETE CASCADE,
|
|
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
|
|
UNIQUE(event_id, user_id)
|
|
);
|
|
|
|
-- Notifications table
|
|
CREATE TABLE IF NOT EXISTS notifications (
|
|
id TEXT PRIMARY KEY,
|
|
user_id TEXT NOT NULL,
|
|
type TEXT NOT NULL, -- friend_request|friend_accepted|post_liked|post_commented|message|match|system
|
|
title TEXT NOT NULL,
|
|
body TEXT,
|
|
data TEXT, -- JSON object with additional data
|
|
is_read INTEGER DEFAULT 0,
|
|
created_at INTEGER NOT NULL,
|
|
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
|
|
);
|
|
|
|
-- Media uploads table
|
|
CREATE TABLE IF NOT EXISTS media (
|
|
id TEXT PRIMARY KEY,
|
|
user_id TEXT NOT NULL,
|
|
filename TEXT NOT NULL,
|
|
original_name TEXT,
|
|
mime_type TEXT,
|
|
size INTEGER,
|
|
url TEXT NOT NULL,
|
|
created_at INTEGER NOT NULL,
|
|
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
|
|
);
|
|
|
|
-- Refresh tokens table for JWT
|
|
CREATE TABLE IF NOT EXISTS refresh_tokens (
|
|
id TEXT PRIMARY KEY,
|
|
user_id TEXT NOT NULL,
|
|
token_hash TEXT NOT NULL,
|
|
expires_at INTEGER NOT NULL,
|
|
created_at INTEGER NOT NULL,
|
|
revoked_at INTEGER,
|
|
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
|
|
);
|
|
|
|
-- Indexes for better performance
|
|
CREATE INDEX IF NOT EXISTS idx_users_email ON users(email);
|
|
CREATE INDEX IF NOT EXISTS idx_users_username ON users(username);
|
|
CREATE INDEX IF NOT EXISTS idx_posts_user_id ON posts(user_id);
|
|
CREATE INDEX IF NOT EXISTS idx_posts_created_at ON posts(created_at);
|
|
CREATE INDEX IF NOT EXISTS idx_relationships_follower ON relationships(follower_id);
|
|
CREATE INDEX IF NOT EXISTS idx_relationships_following ON relationships(following_id);
|
|
CREATE INDEX IF NOT EXISTS idx_chat_messages_chat_id ON chat_messages(chat_id);
|
|
CREATE INDEX IF NOT EXISTS idx_chat_messages_created_at ON chat_messages(created_at);
|
|
CREATE INDEX IF NOT EXISTS idx_notifications_user_id ON notifications(user_id);
|
|
CREATE INDEX IF NOT EXISTS idx_notifications_created_at ON notifications(created_at);
|
|
CREATE INDEX IF NOT EXISTS idx_swipes_user_id ON swipes(user_id);
|
|
CREATE INDEX IF NOT EXISTS idx_matches_user1 ON matches(user1_id);
|
|
CREATE INDEX IF NOT EXISTS idx_matches_user2 ON matches(user2_id);
|