first commit
SAP-ERP Portal CI/CD / build (push) Failing after 5m20s

This commit is contained in:
John
2026-09-23 17:31:02 +05:30
commit 69b4e68baf
51657 changed files with 3864077 additions and 0 deletions
+143
View File
@@ -0,0 +1,143 @@
// backend/routes/auth.js
// Uses HANA ZCUST_USERS table for authentication.
// Roles:
// manager → can view list, open detail, verify/reject, fill manager fields
// sap_adder → all manager perms + approve & push to SAP B1
const express = require('express');
const router = express.Router();
const jwt = require('jsonwebtoken');
const userDb = require('../services/hanaUsers');
const cryptoUtil = require('../services/cryptoUtil');
const sap = require('../services/sapServiceLayer');
const { verifyToken } = require('../middleware/auth');
const SECRET = process.env.JWT_SECRET || 'sap-portal-secret';
const EXPIRES = '12h';
// Build the signed JWT payload for a user, embedding their per-user SAP login
// (SAP password AES-encrypted) so downstream SAP calls can act as them without
// a per-request DB lookup. `creds` is the decrypted { sapUser, sapPassword }
// or null when the user hasn't set one.
function buildPayload(user, creds) {
return {
id: user.id, username: user.username, role: user.role,
name: user.fullName, email: user.email || '',
sapUser: creds ? creds.sapUser : '',
sapPwdEnc: creds ? cryptoUtil.encrypt(creds.sapPassword) : '',
};
}
// ── POST /auth/login ──────────────────────────────────────────────────────────
router.post('/login', async (req, res) => {
const { username, password } = req.body;
if (!username || !password)
return res.status(400).json({ success: false, message: 'Username and password required' });
try {
const user = await userDb.findByUsername(username);
if (!user)
return res.status(401).json({ success: false, message: 'Invalid username or password' });
const ok = await userDb.verifyPassword(password, user.passwordHash);
if (!ok)
return res.status(401).json({ success: false, message: 'Invalid username or password' });
await userDb.touchLastLogin(user.id);
const creds = await userDb.getSapCredentials(user.id); // decrypted or null
const payload = buildPayload(user, creds);
const token = jwt.sign(payload, SECRET, { expiresIn: EXPIRES });
res.json({
success: true,
token,
user: { id: user.id, username: user.username, name: user.fullName, role: user.role, email: user.email, hasSapLogin: !!creds, sapUser: creds ? creds.sapUser : '' },
});
} catch (err) {
console.error('[AUTH] login error:', err.message);
res.status(500).json({ success: false, message: err.message });
}
});
// ── GET /auth/me ──────────────────────────────────────────────────────────────
router.get('/me', (req, res) => {
const token = (req.headers.authorization || '').replace('Bearer ', '');
if (!token) return res.status(401).json({ success: false });
try {
const user = jwt.verify(token, SECRET);
res.json({ success: true, user });
} catch {
res.status(401).json({ success: false });
}
});
// ── GET /auth/profile — full profile from DB ──────────────────────────────────
router.get('/profile', async (req, res) => {
const token = (req.headers.authorization || '').replace('Bearer ', '');
if (!token) return res.status(401).json({ success: false });
try {
const decoded = jwt.verify(token, SECRET);
const user = await userDb.findById(decoded.id);
if (!user) return res.status(404).json({ success: false, message: 'User not found' });
res.json({ success: true, user });
} catch (err) {
res.status(401).json({ success: false, message: err.message });
}
});
// ── GET /auth/sap-credentials — own SAP login status (never the password) ─────
router.get('/sap-credentials', verifyToken, async (req, res) => {
try {
const user = await userDb.findById(req.user.id);
res.json({ success: true, sapUser: user?.sapLoginUser || '', hasSapLogin: !!user?.hasSapLogin });
} catch (err) { res.status(500).json({ success: false, message: err.message }); }
});
// ── PUT /auth/sap-credentials — set own SAP login (validated against SAP) ──────
// Returns a fresh token carrying the new credentials so they take effect
// immediately without re-login.
router.put('/sap-credentials', verifyToken, async (req, res) => {
const sapUser = (req.body?.sapUser || '').trim();
const sapPassword = req.body?.sapPassword || '';
if (!sapUser || !sapPassword)
return res.status(400).json({ success: false, message: 'SAP User ID and Password are required' });
try {
await sap.testSapLogin(null, sapUser, sapPassword); // validate before saving
} catch (e) {
return res.status(400).json({ success: false, message: 'SAP login failed — check your SAP User ID/Password. (' + e.message + ')' });
}
try {
await userDb.setSapCredentials(req.user.id, sapUser, sapPassword);
const user = await userDb.findById(req.user.id);
const token = jwt.sign(buildPayload(user, { sapUser, sapPassword }), SECRET, { expiresIn: EXPIRES });
res.json({ success: true, token, sapUser, hasSapLogin: true });
} catch (err) { res.status(500).json({ success: false, message: err.message }); }
});
// ── PUT /auth/profile — update own name / email / password ────────────────────
router.put('/profile', async (req, res) => {
const token = (req.headers.authorization || '').replace('Bearer ', '');
if (!token) return res.status(401).json({ success: false });
try {
const decoded = jwt.verify(token, SECRET);
const { fullName, email, currentPassword, newPassword } = req.body;
if (newPassword) {
const user = await userDb.findByUsername(decoded.username);
const ok = await userDb.verifyPassword(currentPassword || '', user.passwordHash);
if (!ok) return res.status(400).json({ success: false, message: 'Current password is incorrect' });
}
const patch = {};
if (fullName !== undefined) patch.fullName = fullName.trim();
if (email !== undefined) patch.email = email.trim();
if (newPassword) patch.password = newPassword;
await userDb.updateUser(decoded.id, patch);
res.json({ success: true, message: 'Profile updated successfully' });
} catch (err) {
res.status(500).json({ success: false, message: err.message });
}
});
module.exports = router;