mirror of
https://github.com/Dvorinka/Bookra.git
synced 2026-06-04 20:43:01 +00:00
feat(core): consolidate auth service into backend and implement stripe billing
This commit performs a major architectural refactor by migrating the standalone `auth-service` into the main `backend` application, enabling a unified codebase and simplified deployment. It also introduces comprehensive Stripe billing support and a new administrative dashboard.
Key changes:
- **Architecture**: Deleted `apps/auth-service` and integrated its functionality (JWT, magic links, OAuth, user management) into `apps/backend`.
- **Billing**: Added Stripe integration to `backend`, supporting both monthly and yearly subscription cycles with automatic plan entitlement enforcement (e.g., location limits).
- **Admin Dashboard**: Implemented a new administrative service and API endpoints to manage tenants, users, and view platform-wide statistics.
- **Frontend**:
- Added a new pricing page with monthly/yearly toggle and comparison table.
- Integrated Stripe and Sentry for payments and error tracking.
- Improved dashboard UX/UI and added i18n support for new features.
- Enhanced the public booking flow with better validation and contact form integration.
- **Database**: Added migrations for users, magic links, password resets, OAuth states, admin audit logs, and refresh tokens.
- **DevOps**: Updated environment configurations for Railway and Vercel, and streamlined the project's `package.json` scripts.
This commit is contained in:
@@ -285,3 +285,77 @@ func (p smtpEmailProvider) Send(_ context.Context, message EmailMessage) (Delive
|
||||
ExternalID: fmt.Sprintf("smtp-%d", time.Now().UnixNano()),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// SendContactEmail sends a contact form submission to the business email
|
||||
func (s *Service) SendContactEmail(ctx context.Context, name, email, message string) error {
|
||||
subject := fmt.Sprintf("Bookra Contact: Message from %s", name)
|
||||
text := fmt.Sprintf("Name: %s\nEmail: %s\n\nMessage:\n%s", name, email, message)
|
||||
html := fmt.Sprintf(
|
||||
"<h2>New contact form submission</h2><p><strong>Name:</strong> %s</p><p><strong>Email:</strong> %s</p><p><strong>Message:</strong></p><p>%s</p>",
|
||||
name, email, message,
|
||||
)
|
||||
msg := EmailMessage{
|
||||
From: s.cfg.EmailFrom,
|
||||
To: s.cfg.EmailFrom,
|
||||
Subject: subject,
|
||||
Text: text,
|
||||
HTML: html,
|
||||
}
|
||||
_, err := s.emailProvider.Send(ctx, msg)
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *Service) SendUsageWarning(ctx context.Context, tenantID string, locationCount, locationLimit, usagePercent int) error {
|
||||
tenant, err := s.repo.GetTenantByID(ctx, tenantID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get tenant: %w", err)
|
||||
}
|
||||
|
||||
// Use a placeholder admin email - in production, would get from tenant owner
|
||||
adminEmail := "admin@" + tenant.Slug + ".bookra.eu"
|
||||
|
||||
emailData := UsageNotificationData{
|
||||
Type: EmailTypeUsageWarning,
|
||||
TenantName: tenant.Name,
|
||||
TenantSlug: tenant.Slug,
|
||||
BusinessEmail: s.cfg.EmailFrom,
|
||||
AdminEmail: adminEmail,
|
||||
Locale: tenant.Locale,
|
||||
PlanCode: tenant.PlanCode,
|
||||
LocationCount: locationCount,
|
||||
LocationLimit: locationLimit,
|
||||
UsagePercent: usagePercent,
|
||||
UpgradeURL: "https://bookra.eu/pricing",
|
||||
DashboardURL: "https://bookra.eu/dashboard",
|
||||
}
|
||||
|
||||
msg := RenderUsageNotificationEmail(emailData)
|
||||
_, err = s.emailProvider.Send(ctx, msg)
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *Service) SendTrialEndingEmail(ctx context.Context, tenantID string, daysRemaining int) error {
|
||||
tenant, err := s.repo.GetTenantByID(ctx, tenantID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get tenant: %w", err)
|
||||
}
|
||||
|
||||
// Use a placeholder admin email - in production, would get from tenant owner
|
||||
adminEmail := "admin@" + tenant.Slug + ".bookra.eu"
|
||||
|
||||
emailData := UsageNotificationData{
|
||||
Type: EmailTypeTrialEnding,
|
||||
TenantName: tenant.Name,
|
||||
TenantSlug: tenant.Slug,
|
||||
BusinessEmail: s.cfg.EmailFrom,
|
||||
AdminEmail: adminEmail,
|
||||
Locale: tenant.Locale,
|
||||
PlanCode: tenant.PlanCode,
|
||||
UpgradeURL: "https://bookra.eu/pricing",
|
||||
DashboardURL: "https://bookra.eu/dashboard",
|
||||
}
|
||||
|
||||
msg := RenderUsageNotificationEmail(emailData)
|
||||
_, err = s.emailProvider.Send(ctx, msg)
|
||||
return err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user