doc views by user

This commit is contained in:
Ubuntu 2025-07-23 19:41:42 +05:30
parent ba185c0cf5
commit 7531702923
8 changed files with 88 additions and 125 deletions

View File

@ -1,15 +1,15 @@
DB_HOST=localhost
DB_USER=root
DB_USER=testuser
DB_PASSWORD=Admin@123
DB_NAME=spurrindev
DB_NAME=spurrinai
EMAIL_USER=spurrinai@gmail.com
EMAIL_PASS=wblspqqpzpxfcjaq
EMAIL_USER=info@spurrin.com
EMAIL_PASS=app_password
EMAIL_HOST=smtp.gmail.com
EMAIL_PORT=587
JWT_ACCESS_TOKEN_SECRET=jN4!pY9*d#T2@x$L7wq&Z8^gFc%X5@K#m
JWT_REFRESH_TOKEN_SECRET=Lx$Z7#T2^d&n9!Y4%K8@Fcg*m#qX5p@wL
JWT_ACCESS_TOKEN_EXPIRY=5h
@ -19,12 +19,8 @@ JWT_REFRESH_TOKEN_EXPIRY=7d
BACK_URL = http://localhost:3000/
# email
mail = srikanth.mallikarjuna@tech4biz.io
apppassword = 0peCQnLEZVfZ
# mail = info@spurrin.com
# apppassword=nbF314CF84Ja
mail = info@spurrin.com
apppassword= app_password
# PORT
PORT = 3000
@ -38,6 +34,4 @@ SENDER_SECURITY = false
# SENDER_PORT = 465
# SENDER_SECURITY = true
SSL_CERT = "/home/ubuntu/spurrinai-backend-node/fullchain.pem"
SSL_KEY = "/home/ubuntu/spurrinai-backend-node/privkey.pem"
OPENAI_API_KEY= your_api_key

7
checklist.txt Normal file
View File

@ -0,0 +1,7 @@
CREATE TABLE IF NOT EXISTS document_views (
id INT NOT NULL AUTO_INCREMENT,
document_id INT NOT NULL,
user_id INT NOT NULL,
user_role ENUM('Superadmin', 'Admin', 'Viewer', 'Spurrinadmin', 'AppUser') NOT NULL,
viewed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

View File

@ -6,10 +6,10 @@ A Node.js backend application for SpurrinAI platform.
```
project-root/
├── src/ # Source code
├── src/
│ ├── app.js # App entry point
│ ├── config/ # Configuration files
│ ├── controllers/ # Route controllers
│ ├── controllers/ # Route controllers with business logic
│ ├── middleware/ # Custom middleware
│ ├── migrations/ # Database migrations
│ ├── routes/ # Route definitions
@ -32,8 +32,8 @@ project-root/
1. Clone the repository:
```bash
git clone -b dev https://git.tech4biz.wiki/Tech4Biz-Services/spurrin-cleaned-node.git
cd spurrinai-backend
git clone git_repository_url
cd spurrinai-backend (or respected folder )
```
2. Install dependencies:
@ -58,31 +58,10 @@ npm run setup
```bash
npm run dev
```
2. Run tests:
# Run migrations up
```bash
# Run all tests
npm test
# Run unit tests only
npm run test:unit
# Run integration tests only
npm run test:integration
npm run migrate:up
```
3. Code Quality:
```bash
# Lint code
npm run lint
# Fix linting issues
npm run lint:fix
# Format code
npm run format
```
## Production Mode
1. Build the application:
@ -154,40 +133,6 @@ npm run migrate:up
npm run migrate:down
```
## API Documentation
Detailed API documentation can be found in the [docs/API.md](docs/API.md) file.
## Environment Variables
Required environment variables in `.env`:
```env
# Server Configuration
PORT=3000
NODE_ENV=development
# Database Configuration
DB_HOST=localhost
DB_PORT=5432
DB_NAME=spurrinai
DB_USER=postgres
DB_PASSWORD=your_password
# JWT Configuration
JWT_SECRET=your_jwt_secret
JWT_EXPIRES_IN=24h
# Email Configuration
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_USER=your_email@gmail.com
SMTP_PASS=your_app_password
# File Upload Configuration
UPLOAD_DIR=uploads
MAX_FILE_SIZE=5242880 # 5MB
```
## Support

View File

@ -126,7 +126,7 @@ async function startServer() {
// Root endpoint
app.get('/', (req, res) => {
res.send("SpurrinAI Backend is running!");
res.send("SpurrinAI Backend is running!!!");
});
app.get('/logs', (req, res) => {

View File

@ -174,25 +174,6 @@ exports.getActiveHospitalsAnalysis = async (req, res) => {
`;
// const query = `
// SELECT
// h.id,
// h.name_hospital as hospital_name,
// h.hospital_code,
// h.status,
// h.onboarding_status,
// COUNT(DISTINCT au.id) as total_app_users,
// COUNT(DISTINCT il.id) as total_interactions,
// MAX(il.created_at) as last_interaction_date
// FROM hospitals h
// LEFT JOIN app_users au ON h.hospital_code = au.hospital_code
// LEFT JOIN interaction_logs il ON h.hospital_code = il.hospital_code
// ${start_date && end_date ? 'WHERE il.created_at BETWEEN ? AND ?' : ''}
// GROUP BY h.id
// HAVING total_interactions > 0
// ORDER BY total_interactions DESC
// `;
const params = start_date && end_date ? [start_date, end_date] : [];
const hospitals = await db.query(query, params);

View File

@ -1,13 +1,9 @@
const bcrypt = require("bcrypt");
const db = require("../config/database"); // Database connection
const fs = require("fs");
const JWT_ACCESS_TOKEN_SECRET = process.env.JWT_ACCESS_TOKEN_SECRET;
const JWT_ACCESS_TOKEN_EXPIRY = "5h";
const jwt = require("jsonwebtoken");
const nlp = require("compromise");
const nodemailer = require("nodemailer");
const sender_mail = process.env.mail;
const sender_app_password = process.env.apppassword;
const sender_port = process.env.SENDER_PORT;
const sender_security = process.env.SENDER_SECURITY;
const path = require('path')
@ -24,11 +20,7 @@ const transporter = nodemailer.createTransport({
auth: {
user: "kavya.j@tech4biz.io", // Your Zoho email address
pass: "8pQfkBw8gbrz", // Your Zoho App Password (not your account password)
},
// tls: {
// rejectUnauthorized: false, // Allow self-signed certificates
// minVersion: "TLSv1.2"
// }
}
});
exports.initWebSocket = (io) => {
@ -110,12 +102,6 @@ exports.updateSettings = async (req, res) => {
const userId = req.user.id; // Assuming user is authenticated and userId is available
const { pin, pin_enabled, remember_me } = req.body;
console.log("data---",pin,pin_enabled,remember_me)
// if (typeof pin_enabled !== 'boolean' || typeof remember_me !== 'boolean') {
// return res.status(400).json({ error: 'Invalid data format' });
// }
// Validate pin (if provided)
if (pin && (typeof pin !== 'string' || pin.length !== 4)) {
return res.status(400).json({ error: 'Invalid PIN format. Must be a 4-digit string.' });
@ -211,14 +197,6 @@ exports.signup = async (req, res) => {
try {
const { pin, pin_status,remember_me, email, password, hospital_code, username } = req.body;
console.log("pin--",pin)
console.log("pin_status",pin_status)
console.log("email--",email)
console.log('password---',password)
console.log("hospital_code---",hospital_code)
console.log("username--",username)
console.log("remember_me--",remember_me)
if (!email || !password || !hospital_code || !username) {
return res.status(400).json({
error: "Email, password, username, and hospital code are required",
@ -228,8 +206,6 @@ exports.signup = async (req, res) => {
const pin_enabled = (pin_status === undefined || pin_status === '') ? 0 : pin_status;
const remember_me_ = (remember_me === undefined || remember_me === '') ? 0 : remember_me;
// Check if the hospital_code exists in the `hospitals` table
const hospitalQuery =
"SELECT hospital_code FROM hospitals WHERE hospital_code = ?";
@ -681,8 +657,6 @@ exports.deleteAppUser = async (req, res) => {
const { id } = req.params;
const { hospital_code } = req.user;
console.log('req.user------------------------------------------------------------------',req.user)
// Check if the user exists
const appUserquery = "SELECT * FROM app_users WHERE id = ?";
const users = await db.query(appUserquery, [id]);

View File

@ -497,4 +497,63 @@ exports.updateDocumentViews = async (req, res) => {
console.error('Error updating document views:', error.message);
res.status(500).json({ error: 'Internal server error' });
}
};
};
// POST /documents/:id/view
exports.logDocumentView = async (req, res) => {
const documentId = parseInt(req.params.id);
const userId = req.user.id; // from decoded JWT or session
const userRole = req.user.role; // e.g., 'Admin', 'Viewer', etc.
if (!documentId || !userId || !userRole) {
return res.status(400).json({ error: 'Missing required information' });
}
try {
const insertQuery = `
INSERT INTO document_views (document_id, user_id, user_role)
VALUES (?, ?, ?)
`;
const result = await db.query(insertQuery, [documentId, userId, userRole]);
res.status(200).json({ message: 'View logged successfully', insertId: result.insertId });
} catch (error) {
console.error('Error logging document view:', error.message);
res.status(500).json({ message: 'Error logging view' });
}
};
// GET /documents/:id/views
exports.getDocumentViewCount = async (req, res) => {
const documentId = parseInt(req.params.id);
if (!documentId) {
return res.status(400).json({ error: 'Document ID is required' });
}
try {
const query = `
SELECT
document_id,
user_id AS viewed_by,
user_role,
viewed_at
FROM document_views
WHERE document_id = ?
ORDER BY viewed_at DESC
`;
const [views] = await db.query(query, [documentId]);
res.status(200).json({
documentId,
totalViews: views.length,
views,
});
} catch (error) {
console.error('Error fetching view details:', error.message);
res.status(500).json({ message: 'Error fetching view details' });
}
};

View File

@ -76,5 +76,8 @@ router.delete(
documentController.deleteDocument
);
router.post('/:id/view', authMiddleware.authenticateToken, documentController.logDocumentView);
router.get('/:id/views',authMiddleware.authenticateToken, documentController.getDocumentViewCount);
module.exports = router;
module.exports = router;