feat: Add IP address and browser tracking
- Add database migration for ip_address and browser_info columns - Install ua-parser-js for browser detection - Add IP extraction helper function - Update POST /api/dokumentasi to capture client IP and browser - Update GET endpoints to return tracking data - Display IP and browser info in documentation detail view - Update server port to 3002 Features: - Automatic IP address capture from request headers - Browser and OS detection with version info - Display in detail modal for each documentation
This commit is contained in:
37
server.js
37
server.js
@@ -2,6 +2,7 @@ require('dotenv').config();
|
||||
const express = require('express');
|
||||
const mysql = require('mysql2/promise');
|
||||
const cors = require('cors');
|
||||
const UAParser = require('ua-parser-js');
|
||||
|
||||
const app = express();
|
||||
const PORT = process.env.SERVER_PORT || 3000;
|
||||
@@ -36,6 +37,26 @@ async function testConnection() {
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// HELPER FUNCTIONS
|
||||
// ============================================
|
||||
|
||||
// Get client IP address
|
||||
function getClientIp(req) {
|
||||
return req.headers['x-forwarded-for']?.split(',')[0].trim() ||
|
||||
req.headers['x-real-ip'] ||
|
||||
req.socket.remoteAddress ||
|
||||
req.connection.remoteAddress ||
|
||||
'unknown';
|
||||
}
|
||||
|
||||
// Parse user agent
|
||||
function parseUserAgent(userAgentString) {
|
||||
const parser = new UAParser(userAgentString);
|
||||
const result = parser.getResult();
|
||||
return `${result.browser.name || 'Unknown'} ${result.browser.version || ''} on ${result.os.name || 'Unknown'} ${result.os.version || ''}`;
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// API ENDPOINTS
|
||||
// ============================================
|
||||
@@ -58,16 +79,20 @@ app.post('/api/dokumentasi', async (req, res) => {
|
||||
});
|
||||
}
|
||||
|
||||
// Get IP and browser info
|
||||
const ipAddress = getClientIp(req);
|
||||
const browserInfo = parseUserAgent(req.headers['user-agent'] || '');
|
||||
|
||||
const [result] = await pool.execute(
|
||||
`INSERT INTO dokumentasi (nama, no_anggota, jenis_perjanjian, tanggal, catatan, foto)
|
||||
VALUES (?, ?, ?, ?, ?, ?)`,
|
||||
[nama, noAnggota, jenisPerjanjian, tanggal, catatan || null, foto]
|
||||
`INSERT INTO dokumentasi (nama, no_anggota, jenis_perjanjian, tanggal, catatan, foto, ip_address, browser_info)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
|
||||
[nama, noAnggota, jenisPerjanjian, tanggal, catatan || null, foto, ipAddress, browserInfo]
|
||||
);
|
||||
|
||||
// Log activity
|
||||
await pool.execute(
|
||||
`INSERT INTO activity_log (action, dokumentasi_id, details) VALUES (?, ?, ?)`,
|
||||
['CREATE', result.insertId, `Created documentation for ${nama}`]
|
||||
['CREATE', result.insertId, `Created documentation for ${nama} from ${ipAddress}`]
|
||||
);
|
||||
|
||||
res.status(201).json({
|
||||
@@ -89,7 +114,7 @@ app.get('/api/dokumentasi', async (req, res) => {
|
||||
try {
|
||||
const { search } = req.query;
|
||||
|
||||
let query = 'SELECT id, nama, no_anggota as noAnggota, jenis_perjanjian as jenisPerjanjian, tanggal, catatan, foto, timestamp FROM dokumentasi';
|
||||
let query = 'SELECT id, nama, no_anggota as noAnggota, jenis_perjanjian as jenisPerjanjian, tanggal, catatan, foto, timestamp, ip_address as ipAddress, browser_info as browserInfo FROM dokumentasi';
|
||||
let params = [];
|
||||
|
||||
if (search) {
|
||||
@@ -122,7 +147,7 @@ app.get('/api/dokumentasi/:id', async (req, res) => {
|
||||
|
||||
const [rows] = await pool.execute(
|
||||
`SELECT id, nama, no_anggota as noAnggota, jenis_perjanjian as jenisPerjanjian,
|
||||
tanggal, catatan, foto, timestamp
|
||||
tanggal, catatan, foto, timestamp, ip_address as ipAddress, browser_info as browserInfo
|
||||
FROM dokumentasi WHERE id = ?`,
|
||||
[id]
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user