Phase 1: Foundation - Database schema, core PHP structure, JWT auth, and User CRUD
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
This commit is contained in:
249
www/api/database/schema.sql
Normal file
249
www/api/database/schema.sql
Normal file
@@ -0,0 +1,249 @@
|
||||
-- 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);
|
||||
Reference in New Issue
Block a user