Initial commit: added frontend and backend
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
node_modules
|
||||
.env
|
||||
@@ -0,0 +1,13 @@
|
||||
const mongoose = require('mongoose');
|
||||
|
||||
const connectDB = async () => {
|
||||
try {
|
||||
const conn = await mongoose.connect(process.env.MONGO_URI);
|
||||
console.log(`MongoDB Connected: ${conn.connection.host}`);
|
||||
} catch (error) {
|
||||
console.error(`Error: ${error.message}`);
|
||||
process.exit(1);
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = connectDB;
|
||||
@@ -0,0 +1,56 @@
|
||||
const axios = require('axios');
|
||||
const FormData = require('form-data');
|
||||
|
||||
exports.analyzeImage = async (req, res) => {
|
||||
try {
|
||||
if (!req.file) {
|
||||
return res.status(400).json({ error: 'No image provided' });
|
||||
}
|
||||
|
||||
// In a real scenario, we would forward this to the Perfect Corp API
|
||||
// For now, we will return a mock response matching the expected structure
|
||||
// or you could proxy it like this:
|
||||
/*
|
||||
const formData = new FormData();
|
||||
formData.append('image', req.file.buffer, req.file.originalname);
|
||||
|
||||
const response = await axios.post(process.env.PERFECT_CORP_API_URL, formData, {
|
||||
headers: {
|
||||
...formData.getHeaders(),
|
||||
'Authorization': `Bearer ${process.env.PERFECT_CORP_API_KEY}`
|
||||
}
|
||||
});
|
||||
return res.json({ result: response.data });
|
||||
*/
|
||||
|
||||
// MOCK RESPONSE
|
||||
console.log('Mocking perfect corp analysis for image:', req.file.originalname);
|
||||
|
||||
const mockResult = {
|
||||
results: [
|
||||
{
|
||||
data: [
|
||||
{
|
||||
url: 'https://example.com/mock-mask.zip'
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
// Add other mock data that the frontend expects to parse...
|
||||
face_attributes: {
|
||||
age: 30,
|
||||
gender: 'female'
|
||||
},
|
||||
skin_issues: {
|
||||
wrinkles: 10,
|
||||
spots: 5,
|
||||
acne: 2
|
||||
}
|
||||
};
|
||||
|
||||
res.json({ result: mockResult });
|
||||
} catch (error) {
|
||||
console.error('Error analyzing image:', error);
|
||||
res.status(500).json({ error: 'Failed to analyze image' });
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,27 @@
|
||||
const Report = require('../models/Report');
|
||||
const User = require('../models/User');
|
||||
|
||||
exports.getDashboardUsers = async (req, res) => {
|
||||
try {
|
||||
// Fetch all users
|
||||
const users = await User.find().sort({ createdAt: -1 });
|
||||
|
||||
// We also need the latest report link for each user
|
||||
// In a real scenario, this could be optimized with an aggregation pipeline
|
||||
const dashboardData = await Promise.all(users.map(async (user) => {
|
||||
const latestReport = await Report.findOne({ phone: user.phone }).sort({ createdAt: -1 });
|
||||
|
||||
return {
|
||||
id: user._id,
|
||||
name: user.name,
|
||||
phone: user.phone,
|
||||
lastLink: latestReport ? latestReport.link : null,
|
||||
};
|
||||
}));
|
||||
|
||||
res.json(dashboardData);
|
||||
} catch (error) {
|
||||
console.error('Error fetching dashboard users:', error);
|
||||
res.status(500).json({ success: false, message: 'Server error' });
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,43 @@
|
||||
const Report = require('../models/Report');
|
||||
const User = require('../models/User');
|
||||
|
||||
exports.createReport = async (req, res) => {
|
||||
try {
|
||||
const { reportId, phone, userName, data, link } = req.body;
|
||||
|
||||
if (!reportId || !phone || !data) {
|
||||
return res.status(400).json({ success: false, message: 'Missing required fields' });
|
||||
}
|
||||
|
||||
const report = await Report.create({
|
||||
reportId,
|
||||
phone,
|
||||
userName,
|
||||
data,
|
||||
link
|
||||
});
|
||||
|
||||
res.status(201).json({ success: true, report });
|
||||
} catch (error) {
|
||||
console.error('Error creating report:', error);
|
||||
res.status(500).json({ success: false, message: 'Server error' });
|
||||
}
|
||||
};
|
||||
|
||||
exports.getReport = async (req, res) => {
|
||||
try {
|
||||
const { reportId } = req.params;
|
||||
|
||||
const report = await Report.findOne({ reportId });
|
||||
|
||||
if (!report) {
|
||||
return res.status(404).json({ success: false, message: 'Report not found' });
|
||||
}
|
||||
|
||||
// Return the report data directly to match frontend expectation
|
||||
res.json(report.data);
|
||||
} catch (error) {
|
||||
console.error('Error fetching report:', error);
|
||||
res.status(500).json({ success: false, message: 'Server error' });
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,78 @@
|
||||
const User = require('../models/User');
|
||||
|
||||
exports.createUser = async (req, res) => {
|
||||
try {
|
||||
const { name, phone } = req.body;
|
||||
|
||||
if (!name || !phone) {
|
||||
return res.status(400).json({ success: false, message: 'Name and phone are required' });
|
||||
}
|
||||
|
||||
// Generate a random 4 digit OTP
|
||||
const generatedOtp = Math.floor(1000 + Math.random() * 9000).toString();
|
||||
const otpExpiry = new Date(Date.now() + 10 * 60 * 1000); // 10 minutes from now
|
||||
|
||||
let user = await User.findOne({ phone });
|
||||
let isExisting = false;
|
||||
|
||||
if (user) {
|
||||
isExisting = true;
|
||||
user.otp = generatedOtp;
|
||||
user.otpExpiry = otpExpiry;
|
||||
user.name = name; // Update name just in case
|
||||
await user.save();
|
||||
} else {
|
||||
user = await User.create({
|
||||
name,
|
||||
phone,
|
||||
otp: generatedOtp,
|
||||
otpExpiry
|
||||
});
|
||||
}
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
user: {
|
||||
otp: user.otp,
|
||||
isExisting
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Error creating user:', error);
|
||||
res.status(500).json({ success: false, message: 'Server error' });
|
||||
}
|
||||
};
|
||||
|
||||
exports.verifyOtp = async (req, res) => {
|
||||
try {
|
||||
const { phone, otp } = req.body;
|
||||
|
||||
if (!phone || !otp) {
|
||||
return res.status(400).json({ success: false, message: 'Phone and OTP required' });
|
||||
}
|
||||
|
||||
const user = await User.findOne({ phone });
|
||||
|
||||
if (!user) {
|
||||
return res.status(404).json({ success: false, message: 'User not found' });
|
||||
}
|
||||
|
||||
if (user.otp !== otp) {
|
||||
return res.status(400).json({ success: false, message: 'Invalid OTP' });
|
||||
}
|
||||
|
||||
if (user.otpExpiry < new Date()) {
|
||||
return res.status(400).json({ success: false, message: 'OTP expired' });
|
||||
}
|
||||
|
||||
// Clear OTP after successful verification
|
||||
user.otp = null;
|
||||
user.otpExpiry = null;
|
||||
await user.save();
|
||||
|
||||
res.json({ success: true, message: 'OTP verified successfully' });
|
||||
} catch (error) {
|
||||
console.error('Error verifying OTP:', error);
|
||||
res.status(500).json({ success: false, message: 'Server error' });
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,47 @@
|
||||
exports.sendOtp = async (req, res) => {
|
||||
try {
|
||||
const { phone, name, otpToUse, verificationLink, isExisting } = req.body;
|
||||
|
||||
if (!phone || !otpToUse) {
|
||||
return res.status(400).json({ success: false, message: 'Phone and OTP required' });
|
||||
}
|
||||
|
||||
// Mock WhatsApp API call
|
||||
console.log(`[WhatsApp Mock] Sending OTP ${otpToUse} to ${phone}`);
|
||||
console.log(`[WhatsApp Mock] Verification Link: ${verificationLink}`);
|
||||
|
||||
// In production, use axios to call the real WhatsApp provider API here.
|
||||
/*
|
||||
await axios.post(process.env.WHATSAPP_API_URL, {
|
||||
to: phone,
|
||||
type: "template",
|
||||
template: { ... }
|
||||
}, {
|
||||
headers: { 'Authorization': `Bearer ${process.env.WHATSAPP_API_KEY}` }
|
||||
});
|
||||
*/
|
||||
|
||||
res.json({ success: true, message: 'OTP sent via WhatsApp successfully' });
|
||||
} catch (error) {
|
||||
console.error('Error sending WhatsApp OTP:', error);
|
||||
res.status(500).json({ success: false, message: 'Failed to send OTP' });
|
||||
}
|
||||
};
|
||||
|
||||
exports.sendReport = async (req, res) => {
|
||||
try {
|
||||
const { phone, name, overallScore, origin } = req.body;
|
||||
|
||||
if (!phone || overallScore === undefined) {
|
||||
return res.status(400).json({ success: false, message: 'Phone and overallScore required' });
|
||||
}
|
||||
|
||||
// Mock WhatsApp API call
|
||||
console.log(`[WhatsApp Mock] Sending Report (Score: ${overallScore}) to ${phone}`);
|
||||
|
||||
res.json({ success: true, message: 'Report sent via WhatsApp successfully' });
|
||||
} catch (error) {
|
||||
console.error('Error sending WhatsApp Report:', error);
|
||||
res.status(500).json({ success: false, message: 'Failed to send report' });
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,33 @@
|
||||
const mongoose = require('mongoose');
|
||||
|
||||
const reportSchema = new mongoose.Schema(
|
||||
{
|
||||
reportId: {
|
||||
type: String,
|
||||
required: true,
|
||||
unique: true,
|
||||
},
|
||||
phone: {
|
||||
type: String,
|
||||
required: true,
|
||||
ref: 'User',
|
||||
},
|
||||
userName: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
data: {
|
||||
type: Object, // Store the raw JSON from Perfect Corp
|
||||
required: true,
|
||||
},
|
||||
link: {
|
||||
type: String,
|
||||
},
|
||||
},
|
||||
{
|
||||
timestamps: true,
|
||||
}
|
||||
);
|
||||
|
||||
const Report = mongoose.model('Report', reportSchema);
|
||||
module.exports = Report;
|
||||
@@ -0,0 +1,27 @@
|
||||
const mongoose = require('mongoose');
|
||||
|
||||
const userSchema = new mongoose.Schema(
|
||||
{
|
||||
name: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
phone: {
|
||||
type: String,
|
||||
required: true,
|
||||
unique: true,
|
||||
},
|
||||
otp: {
|
||||
type: String,
|
||||
},
|
||||
otpExpiry: {
|
||||
type: Date,
|
||||
},
|
||||
},
|
||||
{
|
||||
timestamps: true,
|
||||
}
|
||||
);
|
||||
|
||||
const User = mongoose.model('User', userSchema);
|
||||
module.exports = User;
|
||||
Generated
+1746
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"name": "backend",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"axios": "^1.20.0",
|
||||
"cors": "^2.8.6",
|
||||
"dotenv": "^18.0.2",
|
||||
"express": "^5.2.1",
|
||||
"form-data": "^4.0.6",
|
||||
"mongoose": "^9.10.1",
|
||||
"multer": "^2.4.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"nodemon": "^3.1.14"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
const express = require('express');
|
||||
const router = express.Router();
|
||||
const multer = require('multer');
|
||||
|
||||
// Configure multer for memory storage (we'll forward the buffer to the external API)
|
||||
const upload = multer({ storage: multer.memoryStorage() });
|
||||
|
||||
// Controllers
|
||||
const { analyzeImage } = require('../controllers/analysisController');
|
||||
const { createUser, verifyOtp } = require('../controllers/userController');
|
||||
const { createReport, getReport } = require('../controllers/reportController');
|
||||
const { sendOtp, sendReport } = require('../controllers/whatsappController');
|
||||
const { getDashboardUsers } = require('../controllers/dashboardController');
|
||||
|
||||
// 1. Analysis Proxy
|
||||
router.post('/perfectcorp/analyze', upload.single('image'), analyzeImage);
|
||||
|
||||
// 2. User & OTP Management
|
||||
router.post('/users', createUser);
|
||||
router.post('/verify-otp', verifyOtp);
|
||||
|
||||
// 3. Reports
|
||||
router.post('/reports', createReport);
|
||||
router.get('/reports/:reportId', getReport);
|
||||
|
||||
// 4. WhatsApp Integration
|
||||
router.post('/whatsapp/send-otp', sendOtp);
|
||||
router.post('/whatsapp/send-report', sendReport);
|
||||
|
||||
// 5. Admin Dashboard
|
||||
router.get('/dashboard/users', getDashboardUsers);
|
||||
|
||||
module.exports = router;
|
||||
@@ -0,0 +1,24 @@
|
||||
const express = require('express');
|
||||
const cors = require('cors');
|
||||
const dotenv = require('dotenv');
|
||||
const connectDB = require('./config/db');
|
||||
|
||||
// Load env vars
|
||||
dotenv.config();
|
||||
|
||||
// Connect to database
|
||||
connectDB();
|
||||
|
||||
const app = express();
|
||||
|
||||
// Middleware
|
||||
app.use(cors());
|
||||
app.use(express.json());
|
||||
|
||||
// Routes
|
||||
const apiRoutes = require('./routes/api');
|
||||
app.use('/api', apiRoutes);
|
||||
|
||||
const PORT = process.env.PORT || 5000;
|
||||
|
||||
app.listen(PORT, () => console.log(`Server running on port ${PORT}`));
|
||||
Reference in New Issue
Block a user