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>
This commit is contained in:
poduck
2025-11-28 16:44:06 -05:00
parent 4acea4f876
commit a9719a5fd2
77 changed files with 11407 additions and 2694 deletions

View File

@@ -52,6 +52,7 @@
"scheduler": "Planificateur",
"customers": "Clients",
"resources": "Ressources",
"services": "Services",
"payments": "Paiements",
"messages": "Messages",
"staff": "Personnel",
@@ -61,7 +62,124 @@
"businesses": "Entreprises",
"users": "Utilisateurs",
"support": "Support",
"platformSettings": "Paramètres Plateforme"
"platformSettings": "Paramètres Plateforme",
"tickets": "Tickets",
"help": "Aide",
"platformGuide": "Guide de la Plateforme",
"ticketingHelp": "Système de Tickets",
"apiDocs": "Documentation API"
},
"help": {
"guide": {
"title": "Guide de la Plateforme",
"subtitle": "Apprenez à utiliser SmoothSchedule efficacement",
"comingSoon": "Bientôt Disponible",
"comingSoonDesc": "Nous travaillons sur une documentation complète pour vous aider à tirer le meilleur parti de SmoothSchedule. Revenez bientôt !"
},
"api": {
"title": "Référence API",
"interactiveExplorer": "Explorateur Interactif",
"introduction": "Introduction",
"introDescription": "L'API SmoothSchedule est organisée selon REST. Notre API a des URLs prévisibles orientées ressources, accepte des corps de requête encodés en JSON, renvoie des réponses encodées en JSON et utilise des codes de réponse HTTP standard.",
"introTestMode": "Vous pouvez utiliser l'API SmoothSchedule en mode test, qui n'affecte pas vos données en direct. La clé API que vous utilisez détermine si la requête est en mode test ou en direct.",
"baseUrl": "URL de Base",
"baseUrlDescription": "Toutes les requêtes API doivent être faites à :",
"sandboxMode": "Mode Sandbox :",
"sandboxModeDescription": "Utilisez l'URL sandbox pour le développement et les tests. Tous les exemples dans cette documentation utilisent des clés API de test qui fonctionnent avec le sandbox.",
"authentication": "Authentification",
"authDescription": "L'API SmoothSchedule utilise des clés API pour authentifier les requêtes. Vous pouvez voir et gérer vos clés API dans les Paramètres de votre Entreprise.",
"authBearer": "L'authentification à l'API se fait via un token Bearer. Incluez votre clé API dans l'en-tête Authorization de toutes les requêtes.",
"authWarning": "Vos clés API ont de nombreux privilèges, alors assurez-vous de les garder en sécurité. Ne partagez pas vos clés API secrètes dans des zones publiquement accessibles comme GitHub, le code côté client, etc.",
"apiKeyFormat": "Format de Clé API",
"testKey": "Clé mode test/sandbox",
"liveKey": "Clé mode production",
"authenticatedRequest": "Requête Authentifiée",
"keepKeysSecret": "Gardez vos clés secrètes !",
"keepKeysSecretDescription": "N'exposez jamais les clés API dans le code côté client, le contrôle de version ou les forums publics.",
"errors": "Erreurs",
"errorsDescription": "SmoothSchedule utilise des codes de réponse HTTP conventionnels pour indiquer le succès ou l'échec d'une requête API.",
"httpStatusCodes": "Codes de Statut HTTP",
"errorResponse": "Réponse d'Erreur",
"statusOk": "La requête a réussi.",
"statusCreated": "Une nouvelle ressource a été créée.",
"statusBadRequest": "Paramètres de requête invalides.",
"statusUnauthorized": "Clé API invalide ou manquante.",
"statusForbidden": "La clé API n'a pas les permissions requises.",
"statusNotFound": "La ressource demandée n'existe pas.",
"statusConflict": "Conflit de ressources (ex., double réservation).",
"statusTooManyRequests": "Limite de taux dépassée.",
"statusServerError": "Quelque chose s'est mal passé de notre côté.",
"rateLimits": "Limites de Taux",
"rateLimitsDescription": "L'API implémente des limites de taux pour assurer une utilisation équitable et la stabilité.",
"limits": "Limites",
"requestsPerHour": "requêtes par heure par clé API",
"requestsPerMinute": "requêtes par minute limite de rafale",
"rateLimitHeaders": "En-têtes de Limite de Taux",
"rateLimitHeadersDescription": "Chaque réponse inclut des en-têtes avec votre statut actuel de limite de taux.",
"business": "Entreprise",
"businessObject": "L'objet Entreprise",
"businessObjectDescription": "L'objet Entreprise représente la configuration et les paramètres de votre entreprise.",
"attributes": "Attributs",
"retrieveBusiness": "Récupérer l'entreprise",
"retrieveBusinessDescription": "Récupère l'entreprise associée à votre clé API.",
"requiredScope": "Portée requise",
"services": "Services",
"serviceObject": "L'objet Service",
"serviceObjectDescription": "Les services représentent les offres que votre entreprise propose et que les clients peuvent réserver.",
"listServices": "Lister tous les services",
"listServicesDescription": "Renvoie une liste de tous les services actifs de votre entreprise.",
"retrieveService": "Récupérer un service",
"resources": "Ressources",
"resourceObject": "L'objet Ressource",
"resourceObjectDescription": "Les ressources sont les entités réservables dans votre entreprise (membres du personnel, salles, équipements).",
"listResources": "Lister toutes les ressources",
"retrieveResource": "Récupérer une ressource",
"availability": "Disponibilité",
"checkAvailability": "Vérifier la disponibilité",
"checkAvailabilityDescription": "Renvoie les créneaux horaires disponibles pour un service et une plage de dates donnés.",
"parameters": "Paramètres",
"appointments": "Rendez-vous",
"appointmentObject": "L'objet Rendez-vous",
"appointmentObjectDescription": "Les rendez-vous représentent des réservations planifiées entre les clients et les ressources.",
"createAppointment": "Créer un rendez-vous",
"createAppointmentDescription": "Crée une nouvelle réservation de rendez-vous.",
"retrieveAppointment": "Récupérer un rendez-vous",
"updateAppointment": "Mettre à jour un rendez-vous",
"cancelAppointment": "Annuler un rendez-vous",
"listAppointments": "Lister tous les rendez-vous",
"customers": "Clients",
"customerObject": "L'objet Client",
"customerObjectDescription": "Les clients sont les personnes qui réservent des rendez-vous avec votre entreprise.",
"createCustomer": "Créer un client",
"retrieveCustomer": "Récupérer un client",
"updateCustomer": "Mettre à jour un client",
"listCustomers": "Lister tous les clients",
"webhooks": "Webhooks",
"webhookEvents": "Événements webhook",
"webhookEventsDescription": "Les webhooks vous permettent de recevoir des notifications en temps réel lorsque des événements se produisent dans votre entreprise.",
"eventTypes": "Types d'événements",
"webhookPayload": "Charge Webhook",
"createWebhook": "Créer un webhook",
"createWebhookDescription": "Crée un nouvel abonnement webhook. La réponse inclut un secret que vous utiliserez pour vérifier les signatures webhook.",
"secretOnlyOnce": "Le secret n'est affiché qu'une seule fois",
"secretOnlyOnceDescription": ", alors conservez-le en sécurité.",
"listWebhooks": "Lister les webhooks",
"deleteWebhook": "Supprimer un webhook",
"verifySignatures": "Vérifier les signatures",
"verifySignaturesDescription": "Chaque requête webhook inclut une signature dans l'en-tête X-Webhook-Signature. Vous devez vérifier cette signature pour vous assurer que la requête provient de SmoothSchedule.",
"signatureFormat": "Format de signature",
"signatureFormatDescription": "L'en-tête de signature contient deux valeurs séparées par un point : un horodatage et la signature HMAC-SHA256.",
"verificationSteps": "Étapes de vérification",
"verificationStep1": "Extraire l'horodatage et la signature de l'en-tête",
"verificationStep2": "Concaténer l'horodatage, un point et le corps brut de la requête",
"verificationStep3": "Calculer HMAC-SHA256 en utilisant votre secret webhook",
"verificationStep4": "Comparer la signature calculée avec la signature reçue",
"saveYourSecret": "Conservez votre secret !",
"saveYourSecretDescription": "Le secret webhook n'est renvoyé qu'une seule fois lors de la création du webhook. Conservez-le en sécurité pour la vérification des signatures.",
"endpoint": "Point de terminaison",
"request": "Requête",
"response": "Réponse"
}
},
"dashboard": {
"title": "Tableau de Bord",