import express from 'express'; const router = express.Router(); import { DataTypes } from 'sequelize'; import bcrypt from 'bcrypt'; import jwt from 'jsonwebtoken'; import defineUser from '../../models/users.js'; import defineLdapSetting from '../../models/ldapSettings.js'; import { authenticateLdap, getLdapSettings } from '../ldap/ldapClient.js'; import { roles, defaultDangerKey } from './authSettings.js'; export default function (sequelize) { const User = defineUser(sequelize, DataTypes); const LdapSetting = defineLdapSetting(sequelize, DataTypes); const secretKey = process.env.SECRET_KEY || defaultDangerKey; function issueToken(res, user) { const accessToken = jwt.sign({ userId: user.id }, secretKey, { expiresIn: '24h', }); const expiresAt = Date.now() + 3600 * 1000 * 24; // expire date(ms) res.status(200).json({ access_token: accessToken, expires_at: expiresAt, user }); } router.post('/signin', async (req, res) => { try { const { email, password } = req.body; // Local authentication first. This keeps existing accounts (including // the bootstrap administrator) usable even when LDAP is enabled. const user = await User.findOne({ where: { email } }); if (user) { const passwordMatch = await bcrypt.compare(password, user.password); if (passwordMatch) { return issueToken(res, user); } } // Fall back to LDAP when enabled. The email field carries the LDAP login // identifier (substituted into the configured search filter). const ldapSettings = await getLdapSettings(LdapSetting); if (ldapSettings.enabled) { try { const ldapUser = await authenticateLdap(ldapSettings, email, password); // Find-or-create a local user keyed by the directory email. let localUser = user || (await User.findOne({ where: { email: ldapUser.email } })); if (!localUser) { const userRoleIndex = roles.findIndex((entry) => entry.uid === 'user'); const randomPassword = await bcrypt.hash(jwt.sign({ t: Date.now() }, secretKey), 10); localUser = await User.create({ email: ldapUser.email, password: randomPassword, username: ldapUser.username, role: userRoleIndex, }); } return issueToken(res, localUser); } catch (ldapError) { console.error('LDAP authentication failed:', ldapError.message); } } return res.status(401).json({ error: 'Authentication failed' }); } catch (error) { console.error(error); res.status(500).send('Sign in failed'); } }); return router; }