Commit Graph

71 Commits

Author SHA1 Message Date
poduck
2b4104a819 chore(deploy): Update production configuration for ASGI and new URL structure
- Switched production start script from Gunicorn to Daphne to support WebSockets.
- Updated VITE_API_URL in frontend production env to 'https://api.smoothschedule.com', removing the '/api' prefix to align with the backend URL refactor.
2025-12-01 02:44:51 -05:00
poduck
fa3195b3b3 feat(multitenancy): Add TenantHeaderMiddleware to support centralized API with tenant switching
- Implemented TenantHeaderMiddleware to switch the database tenant schema based on the 'X-Business-Subdomain' request header.
- This allows API requests directed to the centralized 'api' subdomain (e.g., api.lvh.me) to correctly access tenant-specific data when the header is present.
- Registered the middleware in multitenancy settings after TenantMainMiddleware.
2025-12-01 02:41:25 -05:00
poduck
980b5d36aa fix(scheduler): Update Timeline to use apiClient for authenticated resource fetching
The Timeline component was using a raw axios instance with hardcoded URLs, causing it to bypass authentication and tenant context headers. This resulted in empty or failed data fetches. Updated it to use the configured 'apiClient', ensuring that the authentication token and 'X-Business-Subdomain' headers are correctly sent, allowing the backend to return the appropriate tenant-specific resources and appointments.
2025-12-01 02:32:48 -05:00
poduck
5cd689af0a fix(auth): Remove hash from email verification URL to support BrowserRouter
The email verification link was incorrectly including a hash fragment (/#/), which caused the React Router (using BrowserRouter) to misinterpret the path as the root path, leading to a redirect to the default 'email-verification-required' page instead of the 'verify-email' page. This commit removes the hash, ensuring the link correctly points to /verify-email.
2025-12-01 02:20:03 -05:00
poduck
b3e2c1f324 refactor(frontend): Remove '/api' prefix from all API calls to align with backend URL convention
- Updated all API endpoint strings in 'frontend/src' (via sed and manual fixes) to remove the '/api/' prefix.
- Manually fixed 'Timeline.tsx' absolute URLs to use the 'api' subdomain and correct path.
- Manually fixed 'useAuth.ts' logout fetch URLs.
- Updated 'HelpApiDocs.tsx' sandbox URL.
- This change, combined with the backend URL update, fully transitions the application to use subdomain-based routing (e.g., 'http://api.lvh.me:8000/resource/') instead of path-prefix routing (e.g., 'http://api.lvh.me:8000/api/resource/').
2025-12-01 02:14:17 -05:00
poduck
92724d03b6 refactor(api): Remove '/api' prefix from frontend API calls and config
- Removed '/api/' prefix from endpoint paths in auth.ts, notifications.ts, oauth.ts, and platform.ts to align with the backend URL reconfiguration.
- Updated 'API_BASE_URL' in config.ts to remove the '/api' suffix, ensuring that API requests are correctly routed to the root of the 'api' subdomain (e.g., http://api.lvh.me:8000/).
- Included improvements to login redirect logic in client.ts.
2025-12-01 01:48:22 -05:00
poduck
2ec78a5237 fix(urls): Remove 'api/' prefix from tickets endpoint to match frontend expectation 2025-12-01 01:45:22 -05:00
poduck
a274d70cec feat(websocket): Resolve ticket WebSocket disconnection/reconnection issue
This commit addresses the persistent WebSocket disconnection and reconnection
problem experienced with ticket updates. The root cause was identified as the
Django backend not running as an ASGI server, which is essential for WebSocket
functionality, and incorrect WebSocket routing.

The following changes were made:

- **Frontend ():**
  - Updated to append the  from cookies to the WebSocket URL's
    query parameter for authentication, ensuring the token is sent with the
    WebSocket connection request.

- **Backend Configuration:**
  - **:** Modified to explicitly
    start the Daphne ASGI server using  instead
    of . This ensures the backend runs in ASGI
    mode, capable of handling WebSocket connections.
  - **:** Removed 'daphne' from
    . Daphne is an ASGI server, not a traditional Django
    application, and its presence in  was causing application
    startup failures.
  - **:**
    - Removed  from  as it
      conflicts with Channels' ASGI server takeover.
    - Explicitly set  to ensure
      the ASGI entry point is correctly referenced.
  - **:** Added 'channels'
    to , ensuring the Channels application is correctly loaded
    within the multi-tenant setup, enabling ASGI functionality.

- **Backend Middleware & Routing:**
  - **:** Implemented a custom
     to authenticate WebSocket connections using an
     from either a query parameter or cookies. This middleware
    ensures proper user authentication for WebSocket sessions. Debugging
    prints with  were added for better visibility.
  - **:** Adjusted WebSocket URL regexes
    to  for robustness, ensuring correct matching
    regardless of leading/trailing slashes in the path.

These changes collectively ensure that WebSocket connections are properly
initiated by the frontend, authenticated by the backend, and served by
an ASGI-compliant server, resolving the frequent disconnection/reconnection
issue.
2025-12-01 01:40:45 -05:00
poduck
be3b5b2d08 Fix: Resolve production CORS issues by moving CorsMiddleware before TenantMainMiddleware
Root cause: CorsMiddleware was positioned after TenantMainMiddleware, which
prevented CORS headers from being set. The tenant middleware processes requests
before CORS middleware could add the necessary headers.

Changes:
- Moved CorsMiddleware to first position in MIDDLEWARE stack
- Added CORS_ALLOW_ALL_ORIGINS configuration (for testing only)
- Updated production CORS regex to match both base and subdomains
- Created public tenant and registered production domains
- Re-enabled CORS_URLS_REGEX for API security

This fix ensures proper CORS headers are sent for cross-origin requests from
smoothschedule.com domains to api.smoothschedule.com.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-30 21:29:00 -05:00
poduck
89f2b570b3 Fix: Move notifications to SHARED_APPS for platform-to-tenant notifications
Platform users need to send notifications to business tenants, so the
notifications app must be in SHARED_APPS (public schema) rather than
TENANT_APPS (tenant-specific schemas).

Changes:
- Moved notifications from TENANT_APPS to SHARED_APPS in multitenancy.py
- Run migrations on public schema to create notifications tables

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-30 21:15:03 -05:00
poduck
885d8bbba2 Fix: Add lvh.me to CORS allowed origins for development
- Added http://lvh.me:5173 and http://lvh.me:5174 to CORS_ALLOWED_ORIGINS
- Added regex pattern to allow all *.lvh.me subdomains in CORS_ALLOWED_ORIGIN_REGEXES
- This allows frontend at lvh.me:5173 to make requests to API at api.lvh.me:8000
- CORS preflight requests now return proper Access-Control-Allow-Origin headers
- Quick login and all API calls from frontend now work without CORS errors

Testing confirmed:
✓ OPTIONS request to /api/auth-token/ returns 200 OK with CORS headers
✓ Access-Control-Allow-Origin: http://lvh.me:5173
✓ Access-Control-Allow-Methods: DELETE, GET, OPTIONS, PATCH, POST, PUT

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-30 21:06:46 -05:00
poduck
c0c037e3b9 Fix: Use api.lvh.me:8000 consistently for development API access
- Changed VITE_API_URL from localhost:8000 to api.lvh.me:8000
- Registered api.lvh.me domain in database pointing to public schema
- This maintains consistency between development and production where
  api subdomain is used for API access
- All test users can now authenticate via quick login

The development setup now mirrors production:
- Production: api.smoothschedule.com → Django API
- Development: api.lvh.me:8000 → Django API (via docker container)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-30 21:05:40 -05:00
poduck
52dde7c95b Fix: Resolve Django settings import error and fix quick login API endpoint
Settings Refactoring Fixes:
- Add minimal LOGGING structure to base.py for multitenancy.py to extend
- Restore LOGGING import in multitenancy.py
- Add development LOGGING configuration to local.py
- This allows multitenancy.py to extend LOGGING configuration properly

Quick Login Fix:
- Update frontend .env.development to use VITE_API_URL=http://localhost:8000
- Previous configuration tried to access api.lvh.me which failed due to
  django-tenants not recognizing that hostname
- Using localhost:8000 directly bypasses subdomain routing and accesses
  the public schema where auth endpoints are available

Both fixes restore full functionality:
- Django now starts without import errors in local development
- Quick login API calls now succeed and return authentication tokens
- Frontend can authenticate users for development/testing

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-30 21:02:24 -05:00
poduck
af92a5ebf4 Refactor: Clean up settings files to eliminate duplication
- Remove duplicate FRONTEND_URL from base.py (was defined twice)
- Move LOGGING configuration from base.py to production.py (production-specific)
- Keep base.py minimal with only universal settings
- Verify EMAIL and AWS/STORAGES are production-only
- Update multitenancy.py import to not reference LOGGING from base.py

This ensures proper separation of concerns:
- base.py: Universal settings (DATABASES, CORS, CSRF, SECURITY basics)
- local.py: Development-specific (CSP, debug tools, console email, eager celery)
- production.py: Production-specific (LOGGING, EMAIL, AWS/S3, SECURITY headers, Sentry)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-30 20:47:48 -05:00
poduck
3ea71408db Refactor: Move CORS and CSRF to base.py with environment variable configuration
- Move CORS_ALLOWED_ORIGINS to base.py, configurable via DJANGO_CORS_ALLOWED_ORIGINS env var
- Move CORS_ALLOWED_ORIGIN_REGEXES to base.py, configurable via DJANGO_CORS_ALLOWED_ORIGIN_REGEXES
- Move CSRF_TRUSTED_ORIGINS to base.py, configurable via DJANGO_CSRF_TRUSTED_ORIGINS
- Remove duplicate CORS/CSRF config from local.py (now inherits from base)
- Remove production-specific CORS config (now uses env vars from base)
- Allows development and production to use same settings with different .env variables
2025-11-30 20:38:00 -05:00
poduck
60708a6417 Add CORS and CSRF configuration to production settings
- Add CORS_ALLOWED_ORIGINS configurable via DJANGO_CORS_ALLOWED_ORIGINS env var
- Add CORS_ALLOWED_ORIGIN_REGEXES for wildcard subdomains
- Add CSRF_TRUSTED_ORIGINS for production domain
- Support custom domains via DJANGO_DOMAIN_NAME env var
- Use corsheaders.defaults for standard CORS headers
- Add custom headers: x-business-subdomain, x-sandbox-mode
2025-11-30 20:37:11 -05:00
poduck
349a54e264 Fix: Remove duplicate middlewares key in Traefik configuration 2025-11-30 20:28:27 -05:00
poduck
c8c0669801 Fix: Correct frontend build context path in production docker-compose 2025-11-30 20:14:32 -05:00
poduck
fa68b4a869 Update README with production deployment guide reference 2025-11-30 20:13:33 -05:00
poduck
b958f9368b Add comprehensive production deployment manual guide 2025-11-30 20:13:19 -05:00
poduck
2b321aef57 Add missing frontend platform components and update production deployment
This commit adds all previously untracked files and modifications needed for production deployment:
- New marketing components (BenefitsSection, CodeBlock, PluginShowcase, PricingTable)
- Platform admin components (EditPlatformEntityModal, PlatformListRow, PlatformListing, PlatformTable)
- Updated deployment configuration and scripts
- Various frontend API and component improvements

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-30 19:49:06 -05:00
poduck
0d1a3045fb Feat: Add marketing site and switch to git-based deployment 2025-11-30 16:18:11 -05:00
poduck
2b28fc49c9 fix: Remove /api/ prefix from all API endpoints
- Fixed double /api/api/ issue in production
- Updated all API files to remove /api/ prefix since baseURL already includes it
- Files fixed: platform.ts, oauth.ts, customDomains.ts, domains.ts, business.ts, sandbox.ts
- Production build will need to be rebuilt after pulling these changes
2025-11-30 16:04:20 -05:00
poduck
4cd6610f2a Fix double /api/ prefix in API endpoint calls
When VITE_API_URL=/api, axios baseURL is already set to /api. However, all endpoint calls included the /api/ prefix, creating double paths like /api/api/auth/login/.

Removed /api/ prefix from 81 API endpoint calls across 22 files:
- src/api/auth.ts - Fixed login, logout, me, refresh, hijack endpoints
- src/api/client.ts - Fixed token refresh endpoint
- src/api/profile.ts - Fixed all profile, email, password, MFA, sessions endpoints
- src/hooks/*.ts - Fixed all remaining API calls (users, appointments, resources, etc)
- src/pages/*.tsx - Fixed signup and email verification endpoints

This ensures API requests use the correct path: /api/auth/login/ instead of /api/api/auth/login/

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-30 15:27:57 -05:00
poduck
f1d4dac9d2 Fix deployment: Inject DATABASE_URL in deploy script 2025-11-30 02:08:36 -05:00
poduck
25db8dd35a Fix API URL duplication: Remove /api suffix from VITE_API_URL 2025-11-30 02:04:43 -05:00
poduck
9eb07a87e6 Fix hardcoded domain redirect: Set FRONTEND_URL in production 2025-11-30 01:59:29 -05:00
poduck
613acf17c1 Fix production 404 errors: Add missing OAuth endpoints and domain script 2025-11-30 01:37:19 -05:00
poduck
3ddd762d74 fix: Add missing Django core apps and DigitalOcean Spaces support
- Add django.contrib.auth, contenttypes, sessions, sites, messages,
  staticfiles, and admin to INSTALLED_APPS
- Add DigitalOcean Spaces (S3-compatible) storage configuration
- Add AWS_S3_ENDPOINT_URL setting for custom S3 endpoints

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-29 21:32:29 -05:00
poduck
7b0cf62019 feat: Add OAuth email integration and production deployment config
- Add OAuthCredential model for storing Google/Microsoft OAuth tokens
- Add email provider auto-detection endpoint (Gmail, Outlook, Yahoo, etc.)
- Add EmailConfigWizard frontend component with step-by-step setup
- Add OAuth flow endpoints for Google and Microsoft XOAUTH2
- Update production settings to make AWS, Sentry, Mailgun optional
- Update Traefik config for wildcard subdomain routing
- Add logo resize utility script

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-29 21:26:17 -05:00
poduck
cfc1b36ada feat: Add SMTP settings and collapsible email configuration UI
- Add SMTP fields to TicketEmailSettings model (host, port, TLS/SSL, credentials, from email/name)
- Update serializers with SMTP fields and is_smtp_configured flag
- Add TicketEmailTestSmtpView for testing SMTP connections
- Update frontend API types and hooks for SMTP settings
- Add collapsible IMAP and SMTP configuration sections with "Configured" badges
- Fix TypeScript errors in mockData.ts (missing required fields, type mismatches)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-29 18:28:29 -05:00
poduck
0c7d76e264 feat: Add event automation system for plugins attached to appointments
- Add GlobalEventPlugin model for auto-attaching plugins to all events
- Create signals for auto-attachment on new events and rescheduling
- Add API endpoints for global event plugins (CRUD, toggle, reapply)
- Update CreateTaskModal with "Scheduled Task" vs "Event Automation" choice
- Add option to apply to all events or future events only
- Display event automations in Tasks page alongside scheduled tasks
- Add EditEventAutomationModal for editing trigger and timing
- Handle event reschedule - update Celery task timing on time/duration changes
- Add Marketplace to Plugins menu in sidebar

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-29 12:17:28 -05:00
poduck
9b106bf129 feat: Add plugin configuration editing with template variable parsing
## Backend Changes:
- Enhanced PluginTemplate.save() to auto-parse template variables from plugin code
- Updated PluginInstallationSerializer to expose template metadata (description, category, version, author, logo, template_variables)
- Fixed template variable parser to handle nested {{ }} braces in default values
- Added brace-counting algorithm to properly extract variables with insertion codes
- Fixed explicit type parameter detection (textarea, text, email, etc.)
- Made scheduled_task optional on PluginInstallation model
- Added EventPlugin through model for event-plugin relationships
- Added Event.execute_plugins() method for plugin automation

## Frontend Changes:
- Created Tasks.tsx page for managing scheduled tasks
- Enhanced MyPlugins page with clickable plugin cards
- Added edit configuration modal with dynamic form generation
- Implemented escape sequence handling (convert \n, \', etc. for display)
- Added plugin logos to My Plugins page
- Updated type definitions for PluginInstallation interface
- Added insertion code documentation to Plugin Docs

## Plugin System:
- All platform plugins now have editable email templates with textarea support
- Template variables properly parsed with full default values
- Insertion codes ({{CUSTOMER_NAME}}, {{BUSINESS_NAME}}, etc.) documented
- Plugin logos displayed in marketplace and My Plugins

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-28 23:45:55 -05:00
poduck
0f46862125 fix: Change Install to View button and fix author display in marketplace
Changes:
1. Changed "Install" button to "View" button with Eye icon
   - Removed separate "Details" button
   - Single "View" button now opens the details modal
2. Fixed author mapping to use author_name from API
3. Fixed rating field to use rating_average from API
4. Set isVerified based on visibility === 'PLATFORM'

The modal now correctly displays:
- Plugin name with verified badge for platform plugins
- Author name (e.g., "Smooth Schedule")
- Version number
- Full description with formatting
- Category, ratings, and install count

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-28 22:01:05 -05:00
poduck
c36025f018 feat: Add description field to PluginTemplateListSerializer
The description field is now included in marketplace listing responses,
allowing the frontend to display full plugin descriptions with formatting,
bullet points, and detailed benefits.

All 6 platform plugins now return complete information:
- Name, author (Smooth Schedule), version (1.0.0)
- Short description (one-line summary)
- Full description (multi-paragraph with bullets)
- Category, ratings, install count

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-28 21:58:57 -05:00
poduck
64ab9ea23c feat: Add version field and enhanced descriptions to platform plugins
Changes:
1. Added version field to PluginTemplate model (default: 1.0.0)
2. Updated platform plugins with detailed descriptions
3. Changed author_name from "SmoothSchedule Platform" to "Smooth Schedule"
4. Enhanced seed_platform_plugins command with comprehensive descriptions

Plugin descriptions now include:
- Detailed explanations of functionality
- Benefits and use cases
- Key features in bullet points

All 6 platform plugins now have:
- Version: 1.0.0
- Author: Smooth Schedule
- Rich, marketing-friendly descriptions

Migration: 0016_plugintemplate_version

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-28 21:56:59 -05:00
poduck
200b7f7930 fix: Include platform plugins in marketplace and fix serializer
Changes:
1. Updated PluginTemplateViewSet.get_queryset() to include PLATFORM
   visibility plugins in marketplace view alongside approved PUBLIC plugins
2. Fixed PluginTemplateListSerializer read_only_fields from string '__all__'
   to proper list reference

Platform plugins are now visible in the marketplace API:
- 6 platform-created plugins seeded via seed_platform_plugins command
- Categories: EMAIL, REPORTS, CUSTOMER, BOOKING
- All marked as visibility=PLATFORM, is_approved=True

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-28 21:50:22 -05:00
poduck
61f43375b9 refactor: Remove Marketplace link from Plugins dropdown
Users can access the marketplace via the "Browse Marketplace" button
on the My Plugins page, so the redundant sidebar link has been removed.

The Plugins dropdown now contains:
- My Plugins
- Plugin Docs

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-28 21:46:28 -05:00
poduck
141eadca8d feat: Add Plugin Marketplace and My Plugins management pages
This commit completes the plugin system UI by adding two key pages:

1. Plugin Marketplace (/plugins/marketplace):
   - Browse and search platform-provided plugins
   - Filter by category (EMAIL, REPORTS, CUSTOMER, BOOKING, etc.)
   - View plugin details including ratings, install count, description
   - Install plugins with one click
   - Modal view for detailed plugin information

2. My Plugins (/plugins/my-plugins):
   - View all installed plugins
   - Manage plugin activation status
   - Update plugins when new versions available
   - Rate and review installed plugins
   - Uninstall plugins with confirmation
   - Links to create custom plugins and browse marketplace

Additional changes:
- Added plugin routes to App.tsx with owner/manager access control
- Updated HelpPluginDocs.tsx with navigation callout boxes
- Added TypeScript interfaces for PluginTemplate and PluginInstallation
- Both pages feature full dark mode support
- Professional UI with Tailwind CSS styling
- React Query integration for data fetching

The pages are accessible from the Plugins dropdown menu in the sidebar.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-28 21:36:50 -05:00
poduck
e234d5fd9c feat: Add Plugins dropdown menu to Business sidebar
- Added Plugins collapsible menu with 3 items:
  - Plugin Marketplace (/plugins/marketplace)
  - My Plugins (/plugins/my-plugins)
  - Plugin Docs (/help/plugins)
- Moved Plugin Docs from Help dropdown to Plugins dropdown
- Added Plug, ShoppingBag, Package icons from lucide-react
- Added translations for plugin navigation items
- Auto-opens dropdown when on /plugins/* routes

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-28 21:29:02 -05:00
poduck
ea6b8fdadd feat: Add plugin marketplace backend infrastructure
Backend Features:
- Created PluginTemplate and PluginInstallation models
- Built complete REST API with marketplace, my plugins, install/uninstall endpoints
- Platform plugins supported (PLATFORM visibility, no whitelisting required)
- Template variable extraction and compilation
- Plugin approval workflow for marketplace publishing
- Rating and review system
- Update detection and version management
- Install count tracking

API Endpoints:
- GET /api/plugin-templates/ - Browse marketplace (view=marketplace/my_plugins/platform)
- POST /api/plugin-templates/ - Create new plugin
- POST /api/plugin-templates/{id}/install/ - Install plugin as ScheduledTask
- POST /api/plugin-templates/{id}/publish/ - Publish to marketplace
- POST /api/plugin-templates/{id}/approve/ - Approve for marketplace (admins)
- POST /api/plugin-installations/{id}/rate/ - Rate and review
- POST /api/plugin-installations/{id}/update_to_latest/ - Update plugin
- DELETE /api/plugin-installations/{id}/ - Uninstall plugin

Platform Plugins:
- Created seed_platform_plugins management command
- 6 starter plugins ready: daily summary, no-show tracker, birthdays, revenue reports, reminders, re-engagement
- Platform plugins bypass whitelist validation
- Pre-approved and available to all businesses

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-28 21:24:27 -05:00
poduck
3723b33cad feat: Add plugin code analysis and HTTP whitelist validation
Implemented static code analysis to detect and validate HTTP calls in plugins
before they are uploaded or approved for the marketplace.

**New Functions:**

1. **analyze_plugin_http_calls(script):**
   - Parses plugin code using Python AST
   - Detects all api.http_* method calls (GET, POST, PUT, PATCH, DELETE)
   - Extracts URL from first argument if it's a string literal
   - Handles dynamic URLs (f-strings, variables) with appropriate warnings
   - Returns list of HTTP calls with method, URL, and line number

2. **validate_plugin_whitelist(script, scheduled_task):**
   - Analyzes plugin code for HTTP calls
   - Validates each detected URL against WhitelistedURL model
   - Checks both platform-wide and plugin-specific whitelists
   - Returns validation results with errors, warnings, and detected calls
   - Provides clear error messages with line numbers

**Validation Logic:**
- **Static URLs** (string literals): Validated against whitelist, error if not found
- **Dynamic URLs** (f-strings, variables): Warning issued, runtime validation required
- **Syntax Errors**: Caught and reported as validation errors
- **Line Numbers**: All errors/warnings include line number for debugging

**Use Cases:**
1. Pre-upload validation: Check plugin before saving to database
2. Approval workflow: Platform staff can see which URLs need whitelisting
3. Marketplace submission: Reject plugins with non-whitelisted URLs
4. Security audit: Analyze existing plugins for HTTP call patterns

**Error Messages:**
- Clear, actionable messages with line numbers
- Direct users to pluginaccess@smoothschedule.com for whitelisting
- Warns about dynamic URLs that can't be statically validated

This enables proactive security enforcement before plugins are executed,
preventing runtime failures and improving user experience.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-28 21:11:26 -05:00
poduck
ecfdbdefe0 refactor: Replace "Platform" with "SmoothSchedule" in licensing section
Updated all references to "Platform" in the licensing documentation to use
"SmoothSchedule" for better branding consistency:

- Changed "Platform Rights" to "SmoothSchedule Rights"
- Changed "Platform Service Rights" to "SmoothSchedule Service Rights"
- Changed "Platform Use" table header to "SmoothSchedule Use"
- Updated all inline references from "Platform" to "SmoothSchedule"

This makes the licensing terms more specific and branded while maintaining
the same legal structure and protections.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-28 21:07:09 -05:00
poduck
79fde43a51 docs: Add comprehensive Plugin Licensing section to documentation
Added new "Plugin Licensing" section to plugin documentation that covers:

**SmoothSchedule Community Plugin License (SCPL):**
- Custom license for marketplace plugins
- Grants platform rights to use, execute, host, and distribute code
- Grants users rights to install, use, and modify for their business
- Requires attribution to original author
- Allows users to adapt code but not republish without permission
- Permits authors to unpublish anytime (existing installs continue)
- Authors retain copyright and can license elsewhere
- Similar to MIT License + Platform Service Rights

**Private vs. Marketplace Plugins:**
- Private plugins: Full ownership, any license (or none), private to business
- Marketplace plugins: Must use SCPL, visible to all users, author credited
- Both types: Platform can execute code to provide automation service

**Key Features:**
- Comparison table showing differences between private and marketplace plugins
- Code verification and security requirements documented
- Decision guide for when to publish vs. keep private
- Important notices about warranties, compliance, and data privacy
- Platform service rights clearly explained

**Legal Protections:**
- Platform has rights to execute user code for service delivery
- No warranty disclaimer (plugins "as-is")
- User compliance responsibility for laws and regulations
- Data privacy obligations (GDPR, CCPA compliance)

The SCPL is designed to be marketplace-friendly while protecting both
the platform and plugin authors, similar to how npm/PyPI handle packages
but with added platform service rights for SaaS execution.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-28 21:05:31 -05:00
poduck
e9b3eb9e84 feat: Add HTTP methods and URL whitelist system for plugins
Backend Changes:
- Extended SafeScriptAPI to support all HTTP methods (GET, POST, PUT, PATCH, DELETE)
- Created WhitelistedURL model for per-plugin and platform-wide URL whitelisting
- Added _validate_url() method with SSRF protection and private IP blocking
- Updated SafeScriptAPI to accept scheduled_task parameter for whitelist checking
- All HTTP methods now validate against whitelist before making requests

WhitelistedURL Model:
- Supports two scopes: PLATFORM (all plugins) and PLUGIN (specific plugin)
- Stores URL patterns with wildcard support (e.g., https://api.example.com/*)
- Tracks allowed HTTP methods per URL
- Includes approval workflow (approved_by, approved_at)
- Stores original plugin code for verification
- Domain-based indexing for fast lookup
- Database constraint ensures platform-wide entries have no plugin assigned

Security Features:
- SSRF prevention: blocks localhost, loopback, and private IP ranges
- Per-plugin whitelist: each ScheduledTask can only access its whitelisted URLs
- Platform-wide whitelist: approved URLs accessible by all plugins
- HTTP method validation: URLs must explicitly allow each method
- URL pattern matching with wildcard support

Related Models:
- WhitelistedURL.scheduled_task -> ScheduledTask (plugin that owns the whitelist)
- WhitelistedURL.approved_by -> User (platform user who approved the URL)

Migration: schedule/migrations/0014_whitelistedurl.py

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-28 21:00:39 -05:00
poduck
3fef0d5749 feat: Add comprehensive plugin documentation and advanced template system
Added complete plugin documentation with visual mockups and expanded template
variable system with CONTEXT, DATE helpers, and default values.

Backend Changes:
- Extended template_parser.py to support all new template types
- Added PROMPT with default values: {{PROMPT:var|desc|default}}
- Added CONTEXT variables: {{CONTEXT:business_name}}, {{CONTEXT:owner_email}}
- Added DATE helpers: {{DATE:today}}, {{DATE:+7d}}, {{DATE:monday}}
- Implemented date expression evaluation for relative dates
- Updated compile_template to handle all template types
- Added context parameter for business data auto-fill

Frontend Changes:
- Created comprehensive HelpPluginDocs.tsx with Stripe-style API docs
- Added visual mockup of plugin configuration form
- Documented all template types with examples and benefits
- Added Command Reference section with allowed/blocked Python commands
- Documented all HTTP methods (GET, POST, PUT, PATCH, DELETE)
- Added URL whitelisting requirements and approval process
- Created Platform Staff management page with edit modal
- Added can_approve_plugins and can_whitelist_urls permissions

Platform Staff Features:
- List all platform_manager and platform_support users
- Edit user details with role-based permissions
- Superusers can edit anyone
- Platform managers can only edit platform_support users
- Permission cascade: users can only grant permissions they have
- Real-time updates via React Query cache invalidation

Documentation Highlights:
- 4 template types: PROMPT, CONTEXT, DATE, and automatic validation
- Visual form mockup showing exactly what users see
- All allowed control flow (if/elif/else, for, while, try/except, etc.)
- All allowed built-in functions (len, range, min, max, etc.)
- All blocked operations (import, exec, eval, class/function defs)
- Complete HTTP API reference with examples
- URL whitelisting process: contact pluginaccess@smoothschedule.com

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-28 20:54:07 -05:00
poduck
a9719a5fd2 feat: Add comprehensive sandbox mode, public API system, and platform support
This commit adds major features for sandbox isolation, public API access, and platform support ticketing.

## Sandbox Mode
- Add sandbox mode toggle for businesses to test features without affecting live data
- Implement schema-based isolation for tenant data (appointments, resources, services)
- Add is_sandbox field filtering for shared models (customers, staff, tickets)
- Create sandbox middleware to detect and set sandbox mode from cookies
- Add sandbox context and hooks for React frontend
- Display sandbox banner when in test mode
- Auto-reload page when switching between live/test modes
- Prevent platform support tickets from being created in sandbox mode

## Public API System
- Full REST API for external integrations with businesses
- API token management with sandbox/live token separation
- Test tokens (ss_test_*) show full plaintext for easy testing
- Live tokens (ss_live_*) are hashed and secure
- Security validation prevents live token plaintext storage
- Comprehensive test suite for token security
- Rate limiting and throttling per token
- Webhook support for real-time event notifications
- Scoped permissions system (read/write per resource type)
- API documentation page with interactive examples
- Token revocation with confirmation modal

## Platform Support
- Dedicated support page for businesses to contact SmoothSchedule
- View all platform support tickets in one place
- Create new support tickets with simplified interface
- Reply to existing tickets with conversation history
- Platform tickets have no admin controls (no priority/category/assignee/status)
- Internal notes hidden for platform tickets (business can't see them)
- Quick help section with links to guides and API docs
- Sandbox warning prevents ticket creation in test mode
- Business ticketing retains full admin controls (priority, assignment, internal notes)

## UI/UX Improvements
- Add notification dropdown with real-time updates
- Staff permissions UI for ticket access control
- Help dropdown in sidebar with Platform Guide, Ticketing Help, API Docs, and Support
- Update sidebar "Contact Support" to "Support" with message icon
- Fix navigation links to use React Router instead of anchor tags
- Remove unused language translations (Japanese, Portuguese, Chinese)

## Technical Details
- Sandbox middleware sets request.sandbox_mode from cookies
- ViewSets filter data by is_sandbox field
- API authentication via custom token auth class
- WebSocket support for real-time ticket updates
- Migration for sandbox fields on User, Tenant, and Ticket models
- Comprehensive documentation in SANDBOX_MODE_IMPLEMENTATION.md

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-28 16:44:06 -05:00
poduck
4acea4f876 feat: Add ticket permission UI and fix assignee dropdown
Assignee Dropdown:
- Fix useUsers hook to fetch from /api/staff/ endpoint
- Add useStaffForAssignment hook for formatted dropdown data
- Update TicketModal to use new hook for assignee selection

Staff Permissions UI:
- Add "Can access support tickets" permission to invite modal for both managers and staff
- Add permission to edit modal for both managers and staff
- Managers default to having ticket access enabled
- Staff default to having ticket access disabled (must be explicitly granted)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-28 05:49:40 -05:00
poduck
9dabb0cb83 feat: Add real-time ticket updates via WebSocket and staff permission control
WebSocket Updates:
- Create useTicketWebSocket hook for real-time ticket list updates
- Hook invalidates React Query cache when tickets are created/updated
- Shows toast notifications for new tickets and comments
- Auto-reconnect with exponential backoff

Staff Permissions:
- Add can_access_tickets() method to User model
- Owners and managers always have ticket access
- Staff members need explicit can_access_tickets permission
- Update Sidebar to conditionally show Tickets menu based on permission
- Add can_access_tickets to API user response

Backend Updates:
- Update ticket signals to broadcast updates to all relevant users
- Check ticket access permission in views

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-28 05:44:39 -05:00
poduck
c400e8a722 fix: Separate platform support tickets from business tickets
- Platform admins now only see PLATFORM tickets from business users
  (tickets where business owners/staff ask for platform help)
- Business owners/managers see CUSTOMER, STAFF_REQUEST, INTERNAL tickets
  for their tenant, plus their own PLATFORM tickets to track support requests
- Removed test platform tickets that were incorrectly created by platform staff

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-28 05:39:40 -05:00