Skip to content

Api#2

Open
samrato wants to merge 2 commits into
FredTechDev:mainfrom
samrato:API
Open

Api#2
samrato wants to merge 2 commits into
FredTechDev:mainfrom
samrato:API

Conversation

@samrato

@samrato samrato commented May 9, 2026

Copy link
Copy Markdown
Contributor

No description provided.

Copilot AI review requested due to automatic review settings May 9, 2026 19:57
@vercel

vercel Bot commented May 9, 2026

Copy link
Copy Markdown

@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.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 thread server/middleware/auth.js
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 thread server/routes/index.js
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 thread .env
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 thread server/ .env.example
Comment on lines +1 to +3
# --- SERVER CONFIG ---
PORT=5000
NODE_ENV=development
Comment thread compose.yaml
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'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants