app versioning

This commit is contained in:
Ubuntu 2025-08-01 16:28:54 +05:30
parent 0766e61de5
commit b3a29c5ffa
5 changed files with 403 additions and 0 deletions

View File

@ -13,3 +13,15 @@ ADD COLUMN is_flagged BOOLEAN DEFAULT FALSE;
ALTER TABLE interaction_logs ALTER TABLE interaction_logs
ADD COLUMN report_text TEXT AFTER is_flagged; ADD COLUMN report_text TEXT AFTER is_flagged;
CREATE TABLE IF NOT EXISTS app_versions (
id INT AUTO_INCREMENT PRIMARY KEY,
platform ENUM('android', 'ios') NOT NULL,
latest_version VARCHAR(20) NOT NULL,
stable_version VARCHAR(20) NOT NULL,
under_maintenance BOOLEAN DEFAULT FALSE,
last_updated DATE NOT NULL,
app_url VARCHAR(500) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
UNIQUE KEY unique_platform (platform)
);

View File

@ -33,6 +33,7 @@ const appUserRoutes = require('./routes/appUsers');
const excelDataRoutes = require('./routes/exceldata'); const excelDataRoutes = require('./routes/exceldata');
const feedbackRoute = require('./routes/feedbacks'); const feedbackRoute = require('./routes/feedbacks');
const analyticsRoute = require('./routes/analysis'); const analyticsRoute = require('./routes/analysis');
const appVersionRoutes = require('./routes/appVersioning');
// Import services // Import services
const { refreshExpiredTokens } = require('./services/cronJobs'); const { refreshExpiredTokens } = require('./services/cronJobs');
@ -102,6 +103,7 @@ async function startServer() {
app.use('/api/process_excel', excelDataRoutes); app.use('/api/process_excel', excelDataRoutes);
app.use('/api/feedbacks', feedbackRoute); app.use('/api/feedbacks', feedbackRoute);
app.use('/api/analytics', analyticsRoute); app.use('/api/analytics', analyticsRoute);
app.use('/api/app-versioning', appVersionRoutes);
// Health check endpoint // Health check endpoint
app.get('/health', (req, res) => { app.get('/health', (req, res) => {

View File

@ -0,0 +1,320 @@
const db = require('../config/database');
// Get all app versions
exports.getAllAppVersions = async (req, res) => {
try {
const query = 'SELECT * FROM app_versions ORDER BY platform';
const rows = await db.query(query);
res.status(200).json({
success: true,
data: rows
});
} catch (error) {
console.error('Error fetching app versions:', error.message);
res.status(500).json({
success: false,
error: 'Internal server error'
});
}
};
// Get app version by platform
exports.getAppVersionByPlatform = async (req, res) => {
try {
const { platform } = req.params;
if (!['android', 'ios'].includes(platform)) {
return res.status(400).json({
success: false,
error: 'Platform must be either "android" or "ios"'
});
}
const query = 'SELECT * FROM app_versions WHERE platform = ?';
const rows = await db.query(query, [platform]);
if (rows.length === 0) {
return res.status(404).json({
success: false,
error: `No app version found for platform: ${platform}`
});
}
res.status(200).json({
success: true,
data: rows[0]
});
} catch (error) {
console.error('Error fetching app version:', error.message);
res.status(500).json({
success: false,
error: 'Internal server error'
});
}
};
// Create new app version
exports.createAppVersion = async (req, res) => {
try {
const {
platform,
latest_version,
stable_version,
under_maintenance = false,
last_updated,
app_url
} = req.body;
// Validate required fields
if (!platform || !latest_version || !stable_version || !last_updated || !app_url) {
return res.status(400).json({
success: false,
error: 'All fields are required: platform, latest_version, stable_version, last_updated, app_url'
});
}
// Validate platform
if (!['android', 'ios'].includes(platform)) {
return res.status(400).json({
success: false,
error: 'Platform must be either "android" or "ios"'
});
}
// Check if platform already exists
const existingQuery = 'SELECT id FROM app_versions WHERE platform = ?';
const existingRows = await db.query(existingQuery, [platform]);
if (existingRows.length > 0) {
return res.status(409).json({
success: false,
error: `App version for platform "${platform}" already exists. Use PUT to update.`
});
}
// Insert new app version
const insertQuery = `
INSERT INTO app_versions (platform, latest_version, stable_version, under_maintenance, last_updated, app_url)
VALUES (?, ?, ?, ?, ?, ?)
`;
const result = await db.query(insertQuery, [
platform,
latest_version,
stable_version,
under_maintenance,
last_updated,
app_url
]);
// Fetch the created record
const newVersion = await db.query('SELECT * FROM app_versions WHERE id = ?', [result.insertId]);
res.status(201).json({
success: true,
message: 'App version created successfully',
data: newVersion[0]
});
} catch (error) {
console.error('Error creating app version:', error.message);
res.status(500).json({
success: false,
error: 'Internal server error'
});
}
};
// Update app version by platform
exports.updateAppVersion = async (req, res) => {
try {
const { platform } = req.params;
const {
latest_version,
stable_version,
under_maintenance,
last_updated,
app_url
} = req.body;
// Validate platform
if (!['android', 'ios'].includes(platform)) {
return res.status(400).json({
success: false,
error: 'Platform must be either "android" or "ios"'
});
}
// Check if platform exists
const existingQuery = 'SELECT id FROM app_versions WHERE platform = ?';
const existingRows = await db.query(existingQuery, [platform]);
if (existingRows.length === 0) {
return res.status(404).json({
success: false,
error: `No app version found for platform: ${platform}`
});
}
// Build update query dynamically based on provided fields
const updateFields = [];
const updateValues = [];
if (latest_version !== undefined) {
updateFields.push('latest_version = ?');
updateValues.push(latest_version);
}
if (stable_version !== undefined) {
updateFields.push('stable_version = ?');
updateValues.push(stable_version);
}
if (under_maintenance !== undefined) {
updateFields.push('under_maintenance = ?');
updateValues.push(under_maintenance);
}
if (last_updated !== undefined) {
updateFields.push('last_updated = ?');
updateValues.push(last_updated);
}
if (app_url !== undefined) {
updateFields.push('app_url = ?');
updateValues.push(app_url);
}
if (updateFields.length === 0) {
return res.status(400).json({
success: false,
error: 'At least one field must be provided for update'
});
}
updateValues.push(platform);
const updateQuery = `
UPDATE app_versions
SET ${updateFields.join(', ')}
WHERE platform = ?
`;
await db.query(updateQuery, updateValues);
// Fetch the updated record
const updatedVersion = await db.query('SELECT * FROM app_versions WHERE platform = ?', [platform]);
res.status(200).json({
success: true,
message: 'App version updated successfully',
data: updatedVersion[0]
});
} catch (error) {
console.error('Error updating app version:', error.message);
res.status(500).json({
success: false,
error: 'Internal server error'
});
}
};
// Delete app version by platform
exports.deleteAppVersion = async (req, res) => {
try {
const { platform } = req.params;
// Validate platform
if (!['android', 'ios'].includes(platform)) {
return res.status(400).json({
success: false,
error: 'Platform must be either "android" or "ios"'
});
}
// Check if platform exists
const existingQuery = 'SELECT id FROM app_versions WHERE platform = ?';
const existingRows = await db.query(existingQuery, [platform]);
if (existingRows.length === 0) {
return res.status(404).json({
success: false,
error: `No app version found for platform: ${platform}`
});
}
// Delete the app version
const deleteQuery = 'DELETE FROM app_versions WHERE platform = ?';
await db.query(deleteQuery, [platform]);
res.status(200).json({
success: true,
message: `App version for platform "${platform}" deleted successfully`
});
} catch (error) {
console.error('Error deleting app version:', error.message);
res.status(500).json({
success: false,
error: 'Internal server error'
});
}
};
// Get app version status (for client apps to check updates)
exports.getAppVersionStatus = async (req, res) => {
try {
const { platform, current_version } = req.query;
// Validate platform
if (!platform || !['android', 'ios'].includes(platform)) {
return res.status(400).json({
success: false,
error: 'Valid platform parameter is required (android or ios)'
});
}
// Get app version for the platform
const query = 'SELECT * FROM app_versions WHERE platform = ?';
const rows = await db.query(query, [platform]);
if (rows.length === 0) {
return res.status(404).json({
success: false,
error: `No app version found for platform: ${platform}`
});
}
const appVersion = rows[0];
// Determine if update is needed
let update_required = false;
let update_type = null;
if (current_version) {
// Simple version comparison (you might want to use a proper semver library)
if (current_version !== appVersion.latest_version) {
update_required = true;
update_type = 'latest';
} else if (current_version !== appVersion.stable_version) {
update_required = true;
update_type = 'stable';
}
}
res.status(200).json({
success: true,
data: {
platform: appVersion.platform,
latest_version: appVersion.latest_version,
stable_version: appVersion.stable_version,
under_maintenance: appVersion.under_maintenance,
last_updated: appVersion.last_updated,
app_url: appVersion.app_url,
update_required,
update_type
}
});
} catch (error) {
console.error('Error fetching app version status:', error.message);
res.status(500).json({
success: false,
error: 'Internal server error'
});
}
};

View File

@ -0,0 +1,28 @@
const db = require('../../config/database');
module.exports = {
async up() {
// Create app_versions table
await db.query(`
CREATE TABLE IF NOT EXISTS app_versions (
id INT AUTO_INCREMENT PRIMARY KEY,
platform ENUM('android', 'ios') NOT NULL,
latest_version VARCHAR(20) NOT NULL,
stable_version VARCHAR(20) NOT NULL,
under_maintenance BOOLEAN DEFAULT FALSE,
last_updated DATE NOT NULL,
app_url VARCHAR(500) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
UNIQUE KEY unique_platform (platform)
)
`);
},
async down() {
// Drop app_versions table
await db.query(`
DROP TABLE IF EXISTS app_versions
`);
}
};

View File

@ -0,0 +1,41 @@
const express = require('express');
const router = express.Router();
const appVersionController = require('../controllers/appVersionController');
const authMiddleware = require('../middlewares/authMiddleware');
const roleMiddleware = require('../middlewares/roleMiddleware');
// Public route - Get app version status (for client apps)
router.get('/status', appVersionController.getAppVersionStatus);
// Protected routes - Require authentication and admin role
// Get all app versions
router.get('/',
authMiddleware.authenticateToken,
appVersionController.getAllAppVersions
);
// Get app version by platform
router.get('/:platform',
authMiddleware.authenticateToken,
appVersionController.getAppVersionByPlatform
);
// Create new app version
router.post('/create',
authMiddleware.authenticateToken,
appVersionController.createAppVersion
);
// Update app version by platform
router.put('/:platform',
authMiddleware.authenticateToken,
appVersionController.updateAppVersion
);
// Delete app version by platform
router.delete('/:platform',
authMiddleware.authenticateToken,
appVersionController.deleteAppVersion
);
module.exports = router;