Api#2
Open
samrato wants to merge 2 commits into
Open
Conversation
|
@samrato is attempting to deploy a commit to the Fredrick Omondi's projects Team on Vercel. A member of the Team first needs to authorize it. |
There was a problem hiding this comment.
Pull request overview
This PR is a major backend + frontend overhaul that migrates the system to PostgreSQL (schema-per-tenant multi-tenancy), adds billing/reminders automation, hardens/standardizes API validation and auth flows, and updates the client UI/UX (including PWA scaffolding) to match the new API responses.
Changes:
- Replace Mongo/Mongoose persistence with Postgres + migrations and tenant-schema routing (
tenantResolver,tenantQuery-based models). - Add subscription billing (Paystack) + automated jobs (billing checks + rent reminders) and new API endpoints/webhooks.
- Refresh client app layout/session handling + add response normalization + introduce PWA assets.
Reviewed changes
Copilot reviewed 125 out of 129 changed files in this pull request and generated 14 comments.
Show a summary per file
| File | Description |
|---|---|
| server/tests/test_endpoints.sh | Wrapper to run endpoint suite |
| server/tests/assets/README.md | Notes for image upload testing |
| server/services/tenantService.js | Tenant schema create/drop helpers |
| server/services/scheduler.js | Daily reminder/billing scheduler |
| server/services/reminderService.js | Auto reminder processing + emails |
| server/services/mpesaService.js | Org-scoped M-Pesa credentials support |
| server/services/emailService.js | Add account-created email template |
| server/services/billingService.js | Paystack init + billing checker |
| server/server.js | Boot Postgres + migrations + scheduler |
| server/scripts/seedSuperAdmin.js | Seed super admin in Postgres |
| server/scripts/seedStarterUsers.js | Seed starter landlord/tenant data |
| server/scripts/seedScenario.js | Demo seed for org/property/units |
| server/routes/units.js | Add request validation |
| server/routes/suggestions.js | Add request validation |
| server/routes/repairs.js | Add validation + delete endpoint |
| server/routes/reminders.js | Add reminder management endpoints |
| server/routes/properties.js | Add validation + delete property |
| server/routes/payments.js | Add validation + settings/methods routes |
| server/routes/messages.js | Add validation + toggle global chat |
| server/routes/leases.js | Add delete lease endpoint |
| server/routes/index.js | Add rate limiter, tenant resolver, webhook |
| server/routes/billing.js | Billing routes for subscription payments |
| server/routes/auth.js | Add validation + inquiry + staff endpoints |
| server/routes/admin.js | Add billing update + pending user approvals |
| server/README.md | Backend docs + setup instructions |
| server/package.json | Add scripts + Postgres deps |
| server/models/User.js | Postgres-backed user model + hashing |
| server/models/Unit.js | Postgres-backed unit model |
| server/models/Tenant.js | Postgres-backed tenant model |
| server/models/Suggestion.js | Postgres-backed suggestion model |
| server/models/Subscription.js | Postgres-backed subscription model |
| server/models/RepairRequest.js | Postgres-backed repairs model + delete |
| server/models/Property.js | Postgres-backed property model |
| server/models/Payment.js | Postgres-backed payment model |
| server/models/OrganizationMembership.js | Org membership join model |
| server/models/Organization.js | Postgres-backed org model + settings |
| server/models/Notification.js | Postgres-backed notifications model |
| server/models/MpesaTransaction.js | Postgres-backed M-Pesa transactions |
| server/models/Message.js | Postgres-backed message model |
| server/models/Lease.js | Postgres-backed lease model + delete |
| server/models/Invoice.js | Postgres-backed invoice model |
| server/models/index.js | Export new membership model |
| server/models/AuditLog.js | Postgres-backed audit logs |
| server/middleware/validation.js | Joi schemas + validation middleware |
| server/middleware/tenantResolver.js | Resolve org/schema + tenant context |
| server/middleware/rateLimiter.js | API rate limiting middleware |
| server/middleware/errorHandler.js | Add AppError + ValidationError |
| server/middleware/authorize.js | Switch to AppError-based denies |
| server/middleware/auth.js | JWT auth + optional auth + password gate |
| server/helpers/upload.js | Switch uploads to Cloudinary storage |
| server/helpers/sql.js | Normalize SQL update fields + SET builder |
| server/helpers/rbac.js | Remove unused roles |
| server/helpers/organization.js | Ensure org + schema for a user |
| server/helpers/notifications.js | Tenant-schema notification creation |
| server/helpers/audit.js | Fix org id resolution for audit logs |
| server/docs/API_DOCUMENTATION.md | New API docs + e2e notes |
| server/docker-compose.yml | Postgres + backend compose (server-local) |
| server/database/migrations/tenant/001_tenant_schema.sql | Base tenant schema tables |
| server/database/migrations/tenant/002_add_property_id_to_messages.sql | Add property-scoped chat column |
| server/database/migrations/public/001_public_schema.sql | Base public schema tables |
| server/database/migrations/public/002_add_requires_password_change.sql | Password-change flag migration |
| server/database/migrations/public/003_add_org_reminder_settings.sql | Reminder settings migration |
| server/database/migrations/public/004_add_global_chat_setting.sql | Global chat flag migration |
| server/database/migrations/public/005_add_org_payment_credentials.sql | Org payment creds migration |
| server/database/migrations/public/006_add_subscription_billing_configs.sql | Subscription billing fields |
| server/database/index.js | Migration runner for public/tenant |
| server/controllers/webhookController.js | Paystack webhook handler |
| server/controllers/unitController.js | Tenant-safe unit access + SQL model mapping |
| server/controllers/suggestionController.js | Tenant-scoped suggestions + property joins |
| server/controllers/repairController.js | Tenant-safe repairs + Cloudinary delete |
| server/controllers/reminderController.js | Reminder settings + manual/trigger-all |
| server/controllers/notificationController.js | SQL-backed notifications + read |
| server/controllers/messageController.js | Property/global chat authorization + toggle |
| server/controllers/leaseController.js | Cloudinary leases + delete/redirect |
| server/controllers/billingController.js | Subscription billing endpoints |
| server/controllers/adminController.js | Admin summary + pending approvals + billing |
| server/config/env.js | Postgres/env/rate-limit/cloudinary configs |
| server/config/database.js | Postgres pool + tenantQuery helpers |
| server/app.js | Health check uses Postgres query |
| server/ .env.example | Example env vars (misnamed path) |
| compose.yaml | Root compose swaps Mongo → Postgres |
| client/vite.config.js | Vite dev proxy config |
| client/src/utils/roles.js | Remove deprecated roles + simplify options |
| client/src/utils/access.js | Route access helper |
| client/src/styles/Dashboard.css | Mobile workspace sidebar tweaks |
| client/src/styles/Auth.css | Separate login/register card sizing |
| client/src/services/repairService.js | Add delete repair call |
| client/src/services/reminderService.js | Update endpoints + new reminder APIs |
| client/src/services/propertyService.js | Add delete property + create tenant |
| client/src/services/paymentService.js | Add settings + methods calls |
| client/src/services/messageService.js | Handle new message payload shape |
| client/src/services/leaseService.js | Add delete lease |
| client/src/services/billingService.js | Add billing endpoints |
| client/src/services/authService.js | Add me/change-password/staff APIs |
| client/src/services/adminService.js | Add pending user + billing update APIs |
| client/src/pages/Register.jsx | Tenant-only “Apply” registration flow |
| client/src/pages/Login.jsx | Handle password-change requirement |
| client/src/pages/Landing.jsx | Update onboarding copy |
| client/src/pages/ChangePassword.jsx | New change-password page |
| client/src/lib/normalize.js | snake_case → camelCase normalization |
| client/src/lib/api.js | Normalize API responses via interceptor |
| client/src/lib/alerts.js | Replace SweetAlert toast with Sonner |
| client/src/index.css | Use theme-driven CSS vars |
| client/src/context/ThemeContext.jsx | Theme provider + CSS var injection |
| client/src/context/SessionContext.jsx | Store orgs + requiresPasswordChange |
| client/src/components/Sidebar.jsx | New sidebar nav + logout |
| client/src/components/Navbar.jsx | Breadcrumb header + workspace display |
| client/src/components/AppLayout.jsx | Layout wrapper for sidebar/header |
| client/src/components/AnimatedSection.jsx | Guard for missing IntersectionObserver |
| client/src/App.jsx | Add theme + toaster + routes |
| client/src/App.css | New layout + sidebar styling |
| client/public/sw.js | Simple service worker cache |
| client/public/manifest.json | PWA manifest |
| client/public/icons/icon.svg | PWA icon |
| client/package.json | Add Sonner dependency |
| client/package-lock.json | Lock Sonner dependency |
| client/nginx.conf | Proxy to backend via host.docker.internal |
| client/index.html | Register service worker + manifest |
| client/.gitignore | Stop ignoring vite config |
| .gitignore | Stop ignoring client vite config |
| .env.example | Root env example updated for Postgres |
| .env | Committed local env overrides (sensitive) |
Files not reviewed (2)
- client/package-lock.json: Language not supported
- server/package-lock.json: Language not supported
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+27
to
+29
| if (user.requires_password_change && req.path !== '/change-password' && req.path !== '/auth/change-password') { | ||
| throw new AppError('Password change required before accessing the system', 403, 'PASSWORD_CHANGE_REQUIRED'); | ||
| } |
Comment on lines
+6
to
+13
| // 1. Verify the Paystack Signature | ||
| const hash = crypto.createHmac('sha512', process.env.PAYSTACK_SECRET_KEY) | ||
| .update(JSON.stringify(req.body)) | ||
| .digest('hex'); | ||
|
|
||
| if (hash !== req.headers['x-paystack-signature']) { | ||
| return res.status(401).send('Invalid signature'); | ||
| } |
Comment on lines
+24
to
+29
| const webhookController = require('../controllers/webhookController'); | ||
|
|
||
| router.use('/auth', authRoutes); | ||
| router.post('/webhooks/paystack', asyncHandler(webhookController.handlePaystackWebhook)); | ||
| router.post('/payments/callback', asyncHandler(paymentController.handleMpesaCallback)); | ||
| router.use(apiRateLimiter); |
Comment on lines
+11
to
+19
| setTimeout(() => { | ||
| runAutoReminders(); | ||
| checkAndGenerateBills(); | ||
| }, 60000); | ||
|
|
||
| setInterval(() => { | ||
| runAutoReminders(); | ||
| checkAndGenerateBills(); | ||
| }, interval); |
Comment on lines
+1
to
+5
| const { Organization, User, Property, Tenant, Invoice, Notification } = require('../models'); | ||
| const { generateReminder } = require('./aiService'); | ||
| const { createNotification } = require('../helpers/notifications'); | ||
| const { sendAccountCreatedEmail } = require('./emailService'); // I might need a more generic email sender | ||
| const nodemailer = require('nodemailer'); |
Comment on lines
+1
to
+15
| # Optional overrides for compose.yaml | ||
| CLIENT_PORT=8081 | ||
| SERVER_PORT=5001 | ||
| DB_PORT=5433 | ||
| DB_NAME=apex_rentals | ||
|
|
||
| # Required for auth flows beyond local smoke tests. | ||
| JWT_SECRET=local-dev-jwt-secret | ||
| JWT_EXPIRES_IN=7d | ||
|
|
||
| # Postgres connection details. | ||
| DB_HOST=localhost | ||
| DB_USER=postgres | ||
| DB_PASSWORD=postgres | ||
|
|
Comment on lines
+1
to
+3
| # --- SERVER CONFIG --- | ||
| PORT=5000 | ||
| NODE_ENV=development |
Comment on lines
41
to
+46
| MPESA_CONSUMER_KEY: ${MPESA_CONSUMER_KEY:-} | ||
| MPESA_CONSUMER_SECRET: ${MPESA_CONSUMER_SECRET:-} | ||
| MPESA_SHORTCODE: ${MPESA_SHORTCODE:-} | ||
| MPESA_PASSKEY: ${MPESA_PASSKEY:-} | ||
| MPESA_CALLBACK_URL: ${MPESA_CALLBACK_URL:-http://localhost:5000/api/payments/callback} | ||
| MPESA_CALLBACK_URL: ${MPESA_CALLBACK_URL:-http://localhost:5001/api/payments/callback} | ||
| CLOUDINARY_CLOUD_NAME: ${CLOUDINARY_CLOUD_NAME:-} |
Comment on lines
39
to
+44
| console.log(JSON.stringify({ | ||
| message: existed ? 'Super admin updated' : 'Super admin created', | ||
| email: user.email, | ||
| password: adminPassword, | ||
| role: user.role, | ||
| organizationId: organizationId.toString() | ||
| }, null, 2)); | ||
| role: user.role | ||
| }, null, 2)); |
Comment on lines
13
to
18
| const organization = await Organization.create({ | ||
| name: fallbackName || `${user.name}'s Portfolio`, | ||
| owner: user._id, | ||
| ownerId: user.id, | ||
| status: user.role === 'super_admin' ? 'active' : 'trial', | ||
| subscriptionPlan: 'basic', | ||
| billingCycle: 'monthly' |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.