# Moxie Backend Express.js backend API for user management of an AI site, built with ESM syntax, Auth0 authentication, and SQLite database. ## Features - **Auth0 Authentication**: Secure authentication via Auth0 - **User Management**: Auto-creation of users on first login, profile management - **Credit System**: Track and manage user credits - **API Keys**: Generate and manage API keys for programmatic access - **Payment Webhooks**: Ready for Stripe and PayPal integration - **Admin Endpoints**: User management for administrators - **SQLite Database**: Lightweight, file-based storage ## Quick Start ```bash # Install dependencies npm install # Copy environment file and configure cp .env.example .env # Edit .env with your Auth0 credentials # Start the server npm start # Start in development mode (with auto-reload) npm run dev ``` The server runs on port 9991 by default. ## Auth0 Setup ### 1. Create Auth0 Application 1. Go to Auth0 Dashboard > Applications > Applications 2. Create a new "Single Page Application" or "Regular Web Application" 3. Configure the following URLs: - **Allowed Callback URLs**: `https://moxiegen.client.guacamolebox.net/api/callback` - **Allowed Logout URLs**: `https://moxiegen.client.guacamolebox.net` - **Allowed Web Origins**: `https://moxiegen.client.guacamolebox.net` - **Application Login URI**: `https://moxiegen.client.guacamolebox.net/login` ### 2. Create Auth0 API (Optional) For machine-to-machine authentication: 1. Go to Auth0 Dashboard > Applications > APIs 2. Create a new API 3. Set the identifier as your audience 4. Enable RBAC if needed ### 3. Configure Environment Variables ```env AUTH0_DOMAIN=your-tenant.auth0.com AUTH0_CLIENT_ID=your-client-id AUTH0_CLIENT_SECRET=your-client-secret AUTH0_AUDIENCE=https://your-tenant.auth0.com/api/v2/ APP_URL=https://moxiegen.client.guacamolebox.net ``` ## API Endpoints ### Auth Endpoints | Method | Endpoint | Description | |--------|----------|-------------| | GET | `/api/login` | Redirect to Auth0 login | | GET | `/api/callback` | Handle Auth0 callback | | GET | `/api/logout` | Logout and redirect | ### User Endpoints (Requires Auth0 Token) All authenticated endpoints require `Authorization: Bearer ` header. | Method | Endpoint | Description | |--------|----------|-------------| | GET | `/api/users/me` | Get current user profile | | PUT | `/api/users/me` | Update profile | | DELETE | `/api/users/me` | Deactivate account | | GET | `/api/users/credits` | Get credits and history | | GET | `/api/users/api-keys` | List API keys | | POST | `/api/users/api-keys` | Create new API key | | DELETE | `/api/users/api-keys/:keyId` | Revoke API key | ### Admin Endpoints (Requires `role: 'admin'`) | Method | Endpoint | Description | |--------|----------|-------------| | GET | `/api/users` | List all users | | GET | `/api/users/:userId` | Get user by ID | | PUT | `/api/users/:userId` | Update user | | DELETE | `/api/users/:userId` | Delete user | | POST | `/api/users/:userId/credits` | Adjust user credits | | PUT | `/api/users/:userId/role` | Change user role | ### Webhook Endpoints | Method | Endpoint | Description | |--------|----------|-------------| | POST | `/api/webhooks/stripe` | Stripe webhook handler | | POST | `/api/webhooks/paypal` | PayPal webhook handler | ## Frontend Integration ### Login Flow ```javascript // Redirect to Auth0 login window.location.href = '/api/login'; // Handle callback (tokens in URL params) const urlParams = new URLSearchParams(window.location.search); const accessToken = urlParams.get('access_token'); const idToken = urlParams.get('id_token'); // Store token and use for API calls localStorage.setItem('access_token', accessToken); // Make authenticated requests fetch('/api/users/me', { headers: { 'Authorization': `Bearer ${accessToken}` } }); ``` ### Using Auth0 SPA SDK ```javascript import { Auth0Client } from '@auth0/auth0-spa-js'; const auth0 = new Auth0Client({ domain: 'your-tenant.auth0.com', client_id: 'your-client-id', redirect_uri: window.location.origin }); // Login await auth0.loginWithRedirect(); // Get token const token = await auth0.getTokenSilently(); // Use token fetch('/api/users/me', { headers: { 'Authorization': `Bearer ${token}` } }); ``` ## Database Schema ### Users Table - `id` - Primary key (UUID) - `auth0_id` - Auth0 user ID (sub claim) - `email` - Email address - `name` - Display name - `picture` - Profile picture URL - `role` - User role ('user' or 'admin') - `credits` - Available credits - `subscription_status` - Subscription state - `subscription_tier` - Subscription level - `stripe_customer_id` - Stripe customer reference - `paypal_customer_id` - PayPal customer reference - `is_active` - Account status flag ### API Keys Table - `id` - Key ID - `user_id` - Foreign key to users - `key_hash` - Hashed API key - `name` - Key name/description - `is_active` - Key status ### Credit Transactions Table - `id` - Transaction ID - `user_id` - Foreign key to users - `amount` - Credit amount (+/-) - `type` - 'credit' or 'debit' - `description` - Transaction description ### Payments Table - `id` - Payment ID - `user_id` - Foreign key to users - `amount` - Payment amount - `provider` - 'stripe' or 'paypal' - `status` - Payment status ## Caddy Configuration ```caddyfile moxiegen.client.guacamolebox.net { # Static site root * /path/to/static/site file_server # API proxy handle /api/* { reverse_proxy localhost:9991 } } ``` ## Making a User Admin To promote a user to admin role: 1. Find the user ID from the database 2. Use the admin API (requires an existing admin) 3. Or directly update the database: ```sql UPDATE users SET role = 'admin' WHERE email = 'admin@example.com'; ``` ## Payment Integration ### Stripe Setup 1. Create a Stripe account and get API keys 2. Add keys to environment variables 3. Create a webhook endpoint in Stripe dashboard pointing to `https://moxiegen.client.guacamolebox.net/api/webhooks/stripe` 4. Copy the webhook signing secret to `STRIPE_WEBHOOK_SECRET` ### PayPal Setup 1. Create a PayPal Developer account 2. Create a REST API application 3. Add credentials to environment variables 4. Configure webhook in PayPal dashboard pointing to `https://moxiegen.client.guacamolebox.net/api/webhooks/paypal` ## Email Configuration (Contact Form) Contact form submissions are automatically emailed to a configured address using Nodemailer with SMTP. ### Setup Add the following to your `.env` file: ```env # SMTP Email Configuration SMTP_HOST=smtp.gmail.com # Your SMTP server SMTP_PORT=587 # Usually 587 (TLS) or 465 (SSL) SMTP_USER=your-email@gmail.com # Email address to send from SMTP_PASS=your-app-password # Password or app-specific password SMTP_SECURE=false # true for port 465, false for 587 SMTP_FROM=Moxie # From display name & address # Where contact form emails are sent (defaults to SMTP_USER) CONTACT_EMAIL=notifications@yourdomain.com ``` ### Gmail Users If you use Gmail, you must generate an **App Password** because regular passwords no longer work with SMTP: 1. Go to [Google Account Security](https://myaccount.google.com/security) 2. Enable **2-Step Verification** (if not already enabled) 3. Go to **App passwords** (search in security settings) 4. Create a new app password for "Mail" 5. Use that 16-character password as `SMTP_PASS` ### Other Providers | Provider | SMTP_HOST | SMTP_PORT | Notes | |----------|-----------|-----------|-------| | Gmail | smtp.gmail.com | 587 | Requires App Password | | Outlook / Office 365 | smtp.office365.com | 587 | | | SendGrid | smtp.sendgrid.net | 587 | Use API key as password | | Mailgun | smtp.mailgun.org | 587 | | | AWS SES | email-smtp.[region].amazonaws.com | 587 | Use SMTP credentials | ### How It Works When someone submits the contact form (`POST /api/contact`): 1. The submission is **saved to the database** (always succeeds) 2. An email notification is **sent in the background** (fire-and-forget) 3. If email sending fails, the form still saves — a warning is logged but the user is not affected The email includes: - Plain-text and HTML versions - The submitter's name, email, and company (if provided) - The full message - A reply-to header so you can reply directly to the submitter ## License ISC