Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
ff444ea
Merge pull request #6 from Fin-Track-AI/develop
AtharvaKalekar Sep 11, 2026
42ca252
Merge pull request #8 from Fin-Track-AI/develop
RiteshJadhav283 Sep 11, 2026
884b563
Merge pull request #11 from Fin-Track-AI/develop
AtharvaKalekar Sep 12, 2026
92d6d65
fix(auth): remove devOtp and enforce real email delivery with SMTP co…
RiteshJadhav283 Sep 12, 2026
a36afcf
Merge pull request #12 from Fin-Track-AI/feat/email-otp-and-user-phone
RiteshJadhav283 Sep 12, 2026
9aa643f
fix(user): align UserModel and UserService with MongoDB schema valida…
RiteshJadhav283 Sep 12, 2026
e7ee08e
Merge pull request #13 from Fin-Track-AI/feat/email-otp-and-user-phone
AtharvaKalekar Sep 12, 2026
3e4b727
feat(backend): prepare backend for mobile connectivity and GCP Cloud …
RiteshJadhav283 Sep 13, 2026
a9aaab1
Merge pull request #14 from Fin-Track-AI/feat/mobile-backend-deployment
RiteshJadhav283 Sep 13, 2026
4c76b56
feat(claims): add employer claim review endpoints, status updates, an…
RiteshJadhav283 Sep 21, 2026
9133f5c
Merge pull request #15 from Fin-Track-AI/feat/employer-claims-sync
AtharvaKalekar Sep 21, 2026
ad02a4c
Reimbursement Management (completion)
AtharvaKalekar Sep 21, 2026
562632c
Resolve merge conflict with origin/main
AtharvaKalekar Sep 21, 2026
afd3e69
Merge pull request #16 from Fin-Track-AI/Reimbursement-Management-Done
RiteshJadhav283 Sep 21, 2026
86a4c7f
Expense Tracking & Insights done
Sep 21, 2026
030efd9
Fix ESLint errors and warnings in budget.service.js and claim.service.js
Sep 21, 2026
74eec37
Merge pull request #17 from Fin-Track-AI/feature/expense-tracking-ins…
RiteshJadhav283 Sep 21, 2026
c13f51d
Split Expenses backend: implement group split models, calculation, de…
SamarthD1 Sep 21, 2026
4ecd1b2
Split Expenses backend: fix ESLint curly rule in split.service.js
SamarthD1 Sep 21, 2026
59268d5
Merge pull request #18 from Fin-Track-AI/Split-Expenses-backend
AtharvaKalekar Sep 21, 2026
da73663
fix(bill-upload): resolve document validation and consent checks for …
RiteshJadhav283 Sep 22, 2026
12d4ee2
fix(ci): fix eslint curly/unused-vars violations and align consent te…
RiteshJadhav283 Sep 22, 2026
f27227b
chore(merge): resolve merge conflict in claim.service.js with origin/…
RiteshJadhav283 Sep 22, 2026
19c67f3
feat(split): implement phone-based member lookup, group deletion, and…
RiteshJadhav283 Sep 23, 2026
ef55756
feat(reimbursement): implement corporate invite codes, company gateke…
RiteshJadhav283 Sep 23, 2026
f98cac3
fix(claims): clear legacy demo claims and filter enrolled employees s…
RiteshJadhav283 Sep 23, 2026
a4e40da
fix(employer): fix join company flow - use employer_links collection,…
RiteshJadhav283 Sep 23, 2026
fb7bbd8
feat(backend): store inviteCode in employer_links, reset on unlink, a…
RiteshJadhav283 Sep 23, 2026
17829c0
feat(backend): add claim receipt image streaming endpoint and enrich …
RiteshJadhav283 Sep 23, 2026
39a10e1
feat(notifications): add notification system, cross-device split invi…
RiteshJadhav283 Sep 23, 2026
6b2bf65
fix(auth): populate phone in JWT and support query fallback for invit…
RiteshJadhav283 Sep 23, 2026
216c44e
Split-Expense-Bug-Fixes
SamarthD1 Sep 23, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,6 @@ SMTP_FROM="FinTrack AI" <your_email@gmail.com>
# SMTP_SECURE=false
# SMTP_USER=apikey
# SMTP_PASS=your_sendgrid_api_key

# Google Gemini AI (Required for OCR Receipt & Bank Statement parsing)
GEMINI_API_KEY=your_gemini_api_key_here
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ node_modules/
dist/
build/
coverage/
uploads/
233 changes: 232 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@
"mongoose": "^9.10.0",
"morgan": "^1.10.0",
"multer": "^2.3.0",
"nodemailer": "^10.0.8"
"nodemailer": "^10.0.8",
"pdf-parse": "^2.4.5",
"uuid": "^14.0.2"
},
"devDependencies": {
"@eslint/js": "^10.0.1",
Expand Down
35 changes: 30 additions & 5 deletions src/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,36 @@ const app = express();
// Security HTTP headers
app.use(helmet({ crossOriginResourcePolicy: { policy: 'cross-origin' } }));

// Enable CORS (Dynamic localhost allowed for Flutter Web dev)
// Enable CORS (supports mobile apps, localhost, and configured client domains)
const allowedOrigins = (config.clientUrl || '*')
.split(',')
.map((s) => s.trim().replace(/\/$/, ''))
.filter(Boolean);

app.use(
cors({
origin: (origin, callback) => {
// Mobile apps, curl, and native HTTP clients send no Origin header
if (!origin) {
return callback(null, true);
}

// Development, wildcard, or local addresses
if (
!origin ||
config.nodeEnv === 'development' ||
allowedOrigins.includes('*') ||
origin.includes('localhost') ||
origin.includes('127.0.0.1')
) {
callback(null, true);
} else {
callback(null, origin === config.clientUrl);
return callback(null, true);
}

const cleanOrigin = origin.replace(/\/$/, '');
if (allowedOrigins.includes(cleanOrigin)) {
return callback(null, true);
}

return callback(null, false);
},
credentials: true,
})
Expand All @@ -39,6 +55,15 @@ if (config.nodeEnv === 'development') {
app.use(express.json());
app.use(express.urlencoded({ extended: true }));

// Root health check for GCP Cloud Run and load balancers
app.get('/health', (req, res) => {
res.status(200).json({
status: 'healthy',
uptime: Math.round(process.uptime()),
timestamp: new Date().toISOString(),
});
});

// Root welcome route
app.get('/', (req, res) => {
res.json({
Expand Down
1 change: 1 addition & 0 deletions src/config/env.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ export const config = {
mongoUri: process.env.MONGO_URI || '',
jwtSecret: process.env.JWT_SECRET || 'dev_secret_key_change_in_production',
jwtExpiresIn: process.env.JWT_EXPIRES_IN || '7d',
geminiApiKey: process.env.GEMINI_API_KEY || '',
};
12 changes: 6 additions & 6 deletions src/controllers/auth.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,13 @@ export const sendEmailOtp = async (req, res, next) => {
// Send email dispatch
const delivery = await EmailService.sendOtpEmail({ email: cleanEmail, otp });

return ApiResponse.success(res, delivery.sent && delivery.method === 'smtp'
? `Verification code delivered to ${cleanEmail}`
: 'Verification code generated (Check email or local console)', {
if (!delivery.sent) {
return ApiResponse.error(res, delivery.error || 'Failed to send verification email. Please check your email configuration.', 500);
}

return ApiResponse.success(res, `Verification code sent to ${cleanEmail}`, {
email: cleanEmail,
deliveredToInbox: delivery.method === 'smtp',
// If delivery failed or SMTP is not yet configured, provide devOtp so user is not blocked
devOtp: delivery.method === 'smtp' ? undefined : otp,
deliveredToInbox: true,
});
} catch (error) {
next(error);
Expand Down
Loading
Loading