feat: implement API usage tracking and admin dashboard
- Added database schema for API tracking system: * api_usage table - tracks all Google Search and Gemini AI calls * user_credits table - prepared for future credits system * admin_users table - controls admin dashboard access - Created comprehensive tracking service (track-api-usage.ts): * trackApiUsage() - records API calls with success/failure * checkDailyLimit() - enforces 80 Google Search calls/day limit * getUserApiStats() - per-user statistics * getGlobalApiStats() - app-wide statistics (admin only) * checkIsAdmin() - server-side authorization - Integrated tracking into discover-whiskybase.ts: * Pre-call limit checking with friendly error messages * Post-call usage tracking for success and failures * User authentication verification - Built admin dashboard at /admin: * Global statistics cards (total, today, by API type) * Top 10 users by API usage * Recent activity log with 50 latest calls * Color-coded status indicators * Secure access with RLS policies - Features: * Daily limit resets at midnight Europe/Berlin timezone * Graceful error handling (allows on tracking failure) * Comprehensive indexes for fast queries * Ready for future credits/monetization system
This commit is contained in:
@@ -229,3 +229,65 @@ CREATE POLICY "Allow authenticated users to view cache"
|
||||
ON vision_cache FOR SELECT
|
||||
TO authenticated
|
||||
USING (true);
|
||||
|
||||
-- ============================================
|
||||
-- API Usage Tracking & Credits System
|
||||
-- ============================================
|
||||
|
||||
-- API Usage tracking table
|
||||
CREATE TABLE IF NOT EXISTS api_usage (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
user_id UUID REFERENCES auth.users(id) ON DELETE CASCADE,
|
||||
api_type TEXT NOT NULL CHECK (api_type IN ('google_search', 'gemini_ai')),
|
||||
endpoint TEXT,
|
||||
success BOOLEAN DEFAULT true,
|
||||
error_message TEXT,
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT timezone('Europe/Berlin'::text, now())
|
||||
);
|
||||
|
||||
CREATE INDEX idx_api_usage_user_id ON api_usage(user_id);
|
||||
CREATE INDEX idx_api_usage_api_type ON api_usage(api_type);
|
||||
CREATE INDEX idx_api_usage_created_at ON api_usage(created_at);
|
||||
CREATE INDEX idx_api_usage_user_date ON api_usage(user_id, DATE(created_at));
|
||||
|
||||
-- User credits table (for future credits system)
|
||||
CREATE TABLE IF NOT EXISTS user_credits (
|
||||
user_id UUID PRIMARY KEY REFERENCES auth.users(id) ON DELETE CASCADE,
|
||||
balance INTEGER DEFAULT 0,
|
||||
total_purchased INTEGER DEFAULT 0,
|
||||
total_used INTEGER DEFAULT 0,
|
||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT timezone('Europe/Berlin'::text, now())
|
||||
);
|
||||
|
||||
-- Admin users table
|
||||
CREATE TABLE IF NOT EXISTS admin_users (
|
||||
user_id UUID PRIMARY KEY REFERENCES auth.users(id) ON DELETE CASCADE,
|
||||
role TEXT DEFAULT 'admin' CHECK (role IN ('admin', 'super_admin')),
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT timezone('Europe/Berlin'::text, now())
|
||||
);
|
||||
|
||||
-- Enable RLS for API tracking tables
|
||||
ALTER TABLE api_usage ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE user_credits ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE admin_users ENABLE ROW LEVEL SECURITY;
|
||||
|
||||
-- Policies for api_usage (users can view their own, admins can view all)
|
||||
CREATE POLICY "Users can view their own API usage" ON api_usage FOR SELECT USING (auth.uid() = user_id);
|
||||
CREATE POLICY "Admins can view all API usage" ON api_usage FOR SELECT USING (
|
||||
EXISTS (SELECT 1 FROM admin_users WHERE user_id = auth.uid())
|
||||
);
|
||||
CREATE POLICY "System can insert API usage" ON api_usage FOR INSERT WITH CHECK (true);
|
||||
|
||||
-- Policies for user_credits
|
||||
CREATE POLICY "Users can view their own credits" ON user_credits FOR SELECT USING (auth.uid() = user_id);
|
||||
CREATE POLICY "Admins can view all credits" ON user_credits FOR SELECT USING (
|
||||
EXISTS (SELECT 1 FROM admin_users WHERE user_id = auth.uid())
|
||||
);
|
||||
|
||||
-- Policies for admin_users (only admins can view)
|
||||
CREATE POLICY "Admins can view admin users" ON admin_users FOR SELECT USING (
|
||||
EXISTS (SELECT 1 FROM admin_users WHERE user_id = auth.uid())
|
||||
);
|
||||
|
||||
-- Note: To add robin as admin, run this after getting the user_id:
|
||||
-- INSERT INTO admin_users (user_id, role) VALUES ('<robin_user_id>', 'super_admin');
|
||||
|
||||
Reference in New Issue
Block a user