Compare commits
2 Commits
327ad064a4
...
2317c46ac9
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2317c46ac9 | ||
|
|
4489f0a74d |
@@ -137,7 +137,7 @@ const authenticateToken = async (req, res, next) => {
|
|||||||
if (!token) return res.status(401).json({ error: 'Token não fornecido.' });
|
if (!token) return res.status(401).json({ error: 'Token não fornecido.' });
|
||||||
|
|
||||||
jwt.verify(token, JWT_SECRET, (err, user) => {
|
jwt.verify(token, JWT_SECRET, (err, user) => {
|
||||||
if (err) return res.status(403).json({ error: 'Token inválido ou expirado.' });
|
if (err) return res.status(401).json({ error: 'Token inválido ou expirado.' });
|
||||||
req.user = user;
|
req.user = user;
|
||||||
next();
|
next();
|
||||||
});
|
});
|
||||||
@@ -203,11 +203,10 @@ apiRouter.post('/auth/verify', async (req, res) => {
|
|||||||
const tenantId = `tenant_${crypto.randomUUID().split('-')[0]}`;
|
const tenantId = `tenant_${crypto.randomUUID().split('-')[0]}`;
|
||||||
const userId = `u_${crypto.randomUUID().split('-')[0]}`;
|
const userId = `u_${crypto.randomUUID().split('-')[0]}`;
|
||||||
|
|
||||||
await connection.query('INSERT INTO tenants (id, name, slug, admin_email) VALUES (?, ?, ?, ?)',
|
await connection.query('INSERT INTO tenants (id, name, slug, admin_email) VALUES (?, ?, ?, ?)',
|
||||||
[tenantId, data.organization_name, data.organization_name.toLowerCase().replace(/ /g, '-'), email]);
|
[tenantId, data.organization_name, data.organization_name.toLowerCase().replace(/ /g, '-'), email]);
|
||||||
await connection.query('INSERT INTO users (id, tenant_id, name, email, password_hash, role) VALUES (?, ?, ?, ?, ?, ?)',
|
await connection.query('INSERT INTO users (id, tenant_id, name, email, password_hash, role) VALUES (?, ?, ?, ?, ?, ?)',
|
||||||
[userId, tenantId, data.full_name, email, data.password_hash, 'owner']);
|
[userId, tenantId, data.full_name, email, data.password_hash, 'admin']); await connection.query('DELETE FROM pending_registrations WHERE email = ?', [email]);
|
||||||
await connection.query('DELETE FROM pending_registrations WHERE email = ?', [email]);
|
|
||||||
|
|
||||||
await connection.commit();
|
await connection.commit();
|
||||||
res.json({ message: 'Sucesso.' });
|
res.json({ message: 'Sucesso.' });
|
||||||
@@ -541,7 +540,8 @@ apiRouter.put('/users/:id', async (req, res) => {
|
|||||||
if (existing.length === 0) return res.status(404).json({ error: 'Not found' });
|
if (existing.length === 0) return res.status(404).json({ error: 'Not found' });
|
||||||
|
|
||||||
const isSelf = req.user.id === req.params.id;
|
const isSelf = req.user.id === req.params.id;
|
||||||
const isManagerOrAdmin = ['admin', 'owner', 'manager', 'super_admin'].includes(req.user.role);
|
const isManagerOrAdmin = ['admin', 'manager', 'super_admin'].includes(req.user.role);
|
||||||
|
const isAdmin = ['admin', 'super_admin'].includes(req.user.role);
|
||||||
|
|
||||||
if (!isSelf && !isManagerOrAdmin) {
|
if (!isSelf && !isManagerOrAdmin) {
|
||||||
return res.status(403).json({ error: 'Acesso negado.' });
|
return res.status(403).json({ error: 'Acesso negado.' });
|
||||||
@@ -551,8 +551,9 @@ apiRouter.put('/users/:id', async (req, res) => {
|
|||||||
return res.status(403).json({ error: 'Acesso negado.' });
|
return res.status(403).json({ error: 'Acesso negado.' });
|
||||||
}
|
}
|
||||||
|
|
||||||
const finalRole = isManagerOrAdmin && role !== undefined ? role : existing[0].role;
|
// Only Admins can change roles and teams. Managers can only edit basic info of their team members.
|
||||||
const finalTeamId = isManagerOrAdmin && team_id !== undefined ? team_id : existing[0].team_id;
|
const finalRole = isAdmin && role !== undefined ? role : existing[0].role;
|
||||||
|
const finalTeamId = isAdmin && team_id !== undefined ? team_id : existing[0].team_id;
|
||||||
const finalStatus = isManagerOrAdmin && status !== undefined ? status : existing[0].status;
|
const finalStatus = isManagerOrAdmin && status !== undefined ? status : existing[0].status;
|
||||||
const finalEmail = email !== undefined ? email : existing[0].email;
|
const finalEmail = email !== undefined ? email : existing[0].email;
|
||||||
const finalSoundEnabled = isSelf && sound_enabled !== undefined ? sound_enabled : (existing[0].sound_enabled ?? true);
|
const finalSoundEnabled = isSelf && sound_enabled !== undefined ? sound_enabled : (existing[0].sound_enabled ?? true);
|
||||||
@@ -584,7 +585,7 @@ apiRouter.put('/users/:id', async (req, res) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
apiRouter.delete('/users/:id', requireRole(['admin', 'owner', 'super_admin']), async (req, res) => {
|
apiRouter.delete('/users/:id', requireRole(['admin', 'super_admin']), async (req, res) => {
|
||||||
try {
|
try {
|
||||||
const [existing] = await pool.query('SELECT tenant_id FROM users WHERE id = ?', [req.params.id]);
|
const [existing] = await pool.query('SELECT tenant_id FROM users WHERE id = ?', [req.params.id]);
|
||||||
if (existing.length === 0) return res.status(404).json({ error: 'Not found' });
|
if (existing.length === 0) return res.status(404).json({ error: 'Not found' });
|
||||||
@@ -733,7 +734,7 @@ apiRouter.get('/origins', async (req, res) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
apiRouter.post('/origins', requireRole(['admin', 'owner', 'manager', 'super_admin']), async (req, res) => {
|
apiRouter.post('/origins', requireRole(['admin', 'manager', 'super_admin']), async (req, res) => {
|
||||||
const { name, tenantId } = req.body;
|
const { name, tenantId } = req.body;
|
||||||
const effectiveTenantId = req.user.role === 'super_admin' ? tenantId : req.user.tenant_id;
|
const effectiveTenantId = req.user.role === 'super_admin' ? tenantId : req.user.tenant_id;
|
||||||
try {
|
try {
|
||||||
@@ -745,7 +746,7 @@ apiRouter.post('/origins', requireRole(['admin', 'owner', 'manager', 'super_admi
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
apiRouter.put('/origins/:id', requireRole(['admin', 'owner', 'manager', 'super_admin']), async (req, res) => {
|
apiRouter.put('/origins/:id', requireRole(['admin', 'manager', 'super_admin']), async (req, res) => {
|
||||||
const { name, teamIds } = req.body;
|
const { name, teamIds } = req.body;
|
||||||
try {
|
try {
|
||||||
if (name) {
|
if (name) {
|
||||||
@@ -763,7 +764,7 @@ apiRouter.put('/origins/:id', requireRole(['admin', 'owner', 'manager', 'super_a
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
apiRouter.delete('/origins/:id', requireRole(['admin', 'owner', 'manager', 'super_admin']), async (req, res) => {
|
apiRouter.delete('/origins/:id', requireRole(['admin', 'manager', 'super_admin']), async (req, res) => {
|
||||||
try {
|
try {
|
||||||
await pool.query('DELETE FROM origin_items WHERE origin_group_id = ?', [req.params.id]);
|
await pool.query('DELETE FROM origin_items WHERE origin_group_id = ?', [req.params.id]);
|
||||||
await pool.query('UPDATE teams SET origin_group_id = NULL WHERE origin_group_id = ?', [req.params.id]);
|
await pool.query('UPDATE teams SET origin_group_id = NULL WHERE origin_group_id = ?', [req.params.id]);
|
||||||
@@ -774,7 +775,7 @@ apiRouter.delete('/origins/:id', requireRole(['admin', 'owner', 'manager', 'supe
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
apiRouter.post('/origins/:id/items', requireRole(['admin', 'owner', 'manager', 'super_admin']), async (req, res) => {
|
apiRouter.post('/origins/:id/items', requireRole(['admin', 'manager', 'super_admin']), async (req, res) => {
|
||||||
const { name, color_class } = req.body;
|
const { name, color_class } = req.body;
|
||||||
try {
|
try {
|
||||||
const oid = `oriitm_${crypto.randomUUID().split('-')[0]}`;
|
const oid = `oriitm_${crypto.randomUUID().split('-')[0]}`;
|
||||||
@@ -788,7 +789,7 @@ apiRouter.post('/origins/:id/items', requireRole(['admin', 'owner', 'manager', '
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
apiRouter.put('/origin_items/:id', requireRole(['admin', 'owner', 'manager', 'super_admin']), async (req, res) => {
|
apiRouter.put('/origin_items/:id', requireRole(['admin', 'manager', 'super_admin']), async (req, res) => {
|
||||||
const { name, color_class } = req.body;
|
const { name, color_class } = req.body;
|
||||||
try {
|
try {
|
||||||
const [existing] = await pool.query('SELECT * FROM origin_items WHERE id = ?', [req.params.id]);
|
const [existing] = await pool.query('SELECT * FROM origin_items WHERE id = ?', [req.params.id]);
|
||||||
@@ -801,7 +802,7 @@ apiRouter.put('/origin_items/:id', requireRole(['admin', 'owner', 'manager', 'su
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
apiRouter.delete('/origin_items/:id', requireRole(['admin', 'owner', 'manager', 'super_admin']), async (req, res) => {
|
apiRouter.delete('/origin_items/:id', requireRole(['admin', 'manager', 'super_admin']), async (req, res) => {
|
||||||
try {
|
try {
|
||||||
await pool.query('DELETE FROM origin_items WHERE id = ?', [req.params.id]);
|
await pool.query('DELETE FROM origin_items WHERE id = ?', [req.params.id]);
|
||||||
res.json({ message: 'Origin item deleted.' });
|
res.json({ message: 'Origin item deleted.' });
|
||||||
@@ -862,7 +863,7 @@ apiRouter.get('/funnels', async (req, res) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
apiRouter.post('/funnels', requireRole(['admin', 'owner', 'manager', 'super_admin']), async (req, res) => {
|
apiRouter.post('/funnels', requireRole(['admin', 'manager', 'super_admin']), async (req, res) => {
|
||||||
const { name, tenantId } = req.body;
|
const { name, tenantId } = req.body;
|
||||||
const effectiveTenantId = req.user.role === 'super_admin' ? tenantId : req.user.tenant_id;
|
const effectiveTenantId = req.user.role === 'super_admin' ? tenantId : req.user.tenant_id;
|
||||||
try {
|
try {
|
||||||
@@ -874,7 +875,7 @@ apiRouter.post('/funnels', requireRole(['admin', 'owner', 'manager', 'super_admi
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
apiRouter.put('/funnels/:id', requireRole(['admin', 'owner', 'manager', 'super_admin']), async (req, res) => {
|
apiRouter.put('/funnels/:id', requireRole(['admin', 'manager', 'super_admin']), async (req, res) => {
|
||||||
const { name, teamIds } = req.body;
|
const { name, teamIds } = req.body;
|
||||||
try {
|
try {
|
||||||
if (name) {
|
if (name) {
|
||||||
@@ -892,7 +893,7 @@ apiRouter.put('/funnels/:id', requireRole(['admin', 'owner', 'manager', 'super_a
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
apiRouter.delete('/funnels/:id', requireRole(['admin', 'owner', 'manager', 'super_admin']), async (req, res) => {
|
apiRouter.delete('/funnels/:id', requireRole(['admin', 'manager', 'super_admin']), async (req, res) => {
|
||||||
try {
|
try {
|
||||||
await pool.query('DELETE FROM funnel_stages WHERE funnel_id = ?', [req.params.id]);
|
await pool.query('DELETE FROM funnel_stages WHERE funnel_id = ?', [req.params.id]);
|
||||||
await pool.query('UPDATE teams SET funnel_id = NULL WHERE funnel_id = ?', [req.params.id]);
|
await pool.query('UPDATE teams SET funnel_id = NULL WHERE funnel_id = ?', [req.params.id]);
|
||||||
@@ -903,7 +904,7 @@ apiRouter.delete('/funnels/:id', requireRole(['admin', 'owner', 'manager', 'supe
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
apiRouter.post('/funnels/:id/stages', requireRole(['admin', 'owner', 'manager', 'super_admin']), async (req, res) => {
|
apiRouter.post('/funnels/:id/stages', requireRole(['admin', 'manager', 'super_admin']), async (req, res) => {
|
||||||
const { name, color_class, order_index } = req.body;
|
const { name, color_class, order_index } = req.body;
|
||||||
try {
|
try {
|
||||||
const sid = `stage_${crypto.randomUUID().split('-')[0]}`;
|
const sid = `stage_${crypto.randomUUID().split('-')[0]}`;
|
||||||
@@ -917,7 +918,7 @@ apiRouter.post('/funnels/:id/stages', requireRole(['admin', 'owner', 'manager',
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
apiRouter.put('/funnel_stages/:id', requireRole(['admin', 'owner', 'manager', 'super_admin']), async (req, res) => {
|
apiRouter.put('/funnel_stages/:id', requireRole(['admin', 'manager', 'super_admin']), async (req, res) => {
|
||||||
const { name, color_class, order_index } = req.body;
|
const { name, color_class, order_index } = req.body;
|
||||||
try {
|
try {
|
||||||
const [existing] = await pool.query('SELECT * FROM funnel_stages WHERE id = ?', [req.params.id]);
|
const [existing] = await pool.query('SELECT * FROM funnel_stages WHERE id = ?', [req.params.id]);
|
||||||
@@ -933,7 +934,7 @@ apiRouter.put('/funnel_stages/:id', requireRole(['admin', 'owner', 'manager', 's
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
apiRouter.delete('/funnel_stages/:id', requireRole(['admin', 'owner', 'manager', 'super_admin']), async (req, res) => {
|
apiRouter.delete('/funnel_stages/:id', requireRole(['admin', 'manager', 'super_admin']), async (req, res) => {
|
||||||
try {
|
try {
|
||||||
await pool.query('DELETE FROM funnel_stages WHERE id = ?', [req.params.id]);
|
await pool.query('DELETE FROM funnel_stages WHERE id = ?', [req.params.id]);
|
||||||
res.json({ message: 'Stage deleted.' });
|
res.json({ message: 'Stage deleted.' });
|
||||||
@@ -958,7 +959,7 @@ apiRouter.get('/search', async (req, res) => {
|
|||||||
|
|
||||||
if (req.user.role === 'super_admin') {
|
if (req.user.role === 'super_admin') {
|
||||||
// No extra filters
|
// No extra filters
|
||||||
} else if (req.user.role === 'admin' || req.user.role === 'owner') {
|
} else if (req.user.role === 'admin') {
|
||||||
membersQ += ' AND tenant_id = ?';
|
membersQ += ' AND tenant_id = ?';
|
||||||
membersParams.push(req.user.tenant_id);
|
membersParams.push(req.user.tenant_id);
|
||||||
} else if (req.user.role === 'manager') {
|
} else if (req.user.role === 'manager') {
|
||||||
@@ -976,7 +977,7 @@ apiRouter.get('/search', async (req, res) => {
|
|||||||
|
|
||||||
if (req.user.role === 'super_admin') {
|
if (req.user.role === 'super_admin') {
|
||||||
// No extra filters
|
// No extra filters
|
||||||
} else if (req.user.role === 'admin' || req.user.role === 'owner') {
|
} else if (req.user.role === 'admin') {
|
||||||
teamsQ += ' AND tenant_id = ?';
|
teamsQ += ' AND tenant_id = ?';
|
||||||
teamsParams.push(req.user.tenant_id);
|
teamsParams.push(req.user.tenant_id);
|
||||||
} else if (req.user.role === 'manager') {
|
} else if (req.user.role === 'manager') {
|
||||||
@@ -999,7 +1000,7 @@ apiRouter.get('/search', async (req, res) => {
|
|||||||
|
|
||||||
if (req.user.role === 'super_admin') {
|
if (req.user.role === 'super_admin') {
|
||||||
// No extra filters
|
// No extra filters
|
||||||
} else if (req.user.role === 'admin' || req.user.role === 'owner') {
|
} else if (req.user.role === 'admin') {
|
||||||
attendancesQ += ' AND a.tenant_id = ?';
|
attendancesQ += ' AND a.tenant_id = ?';
|
||||||
attendancesParams.push(req.user.tenant_id);
|
attendancesParams.push(req.user.tenant_id);
|
||||||
} else if (req.user.role === 'manager') {
|
} else if (req.user.role === 'manager') {
|
||||||
@@ -1090,7 +1091,7 @@ apiRouter.get('/attendances/:id', async (req, res) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// --- API Key Management Routes ---
|
// --- API Key Management Routes ---
|
||||||
apiRouter.get('/api-keys', requireRole(['admin', 'owner', 'super_admin']), async (req, res) => {
|
apiRouter.get('/api-keys', requireRole(['admin', 'super_admin']), async (req, res) => {
|
||||||
try {
|
try {
|
||||||
const { tenantId } = req.query;
|
const { tenantId } = req.query;
|
||||||
const effectiveTenantId = req.user.role === 'super_admin' ? tenantId : req.user.tenant_id;
|
const effectiveTenantId = req.user.role === 'super_admin' ? tenantId : req.user.tenant_id;
|
||||||
@@ -1103,7 +1104,7 @@ apiRouter.get('/api-keys', requireRole(['admin', 'owner', 'super_admin']), async
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
apiRouter.post('/api-keys', requireRole(['admin', 'owner', 'super_admin']), async (req, res) => {
|
apiRouter.post('/api-keys', requireRole(['admin', 'super_admin']), async (req, res) => {
|
||||||
const { name, tenantId } = req.body;
|
const { name, tenantId } = req.body;
|
||||||
const effectiveTenantId = req.user.role === 'super_admin' ? tenantId : req.user.tenant_id;
|
const effectiveTenantId = req.user.role === 'super_admin' ? tenantId : req.user.tenant_id;
|
||||||
try {
|
try {
|
||||||
@@ -1123,7 +1124,7 @@ apiRouter.post('/api-keys', requireRole(['admin', 'owner', 'super_admin']), asyn
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
apiRouter.delete('/api-keys/:id', requireRole(['admin', 'owner', 'super_admin']), async (req, res) => {
|
apiRouter.delete('/api-keys/:id', requireRole(['admin', 'super_admin']), async (req, res) => {
|
||||||
try {
|
try {
|
||||||
const [existing] = await pool.query('SELECT tenant_id FROM api_keys WHERE id = ?', [req.params.id]);
|
const [existing] = await pool.query('SELECT tenant_id FROM api_keys WHERE id = ?', [req.params.id]);
|
||||||
if (existing.length === 0) return res.status(404).json({ error: 'Chave não encontrada' });
|
if (existing.length === 0) return res.status(404).json({ error: 'Chave não encontrada' });
|
||||||
@@ -1153,8 +1154,19 @@ apiRouter.get('/integration/users', requireRole(['admin']), async (req, res) =>
|
|||||||
apiRouter.get('/integration/origins', requireRole(['admin']), async (req, res) => {
|
apiRouter.get('/integration/origins', requireRole(['admin']), async (req, res) => {
|
||||||
if (!req.user.is_api_key) return res.status(403).json({ error: 'Endpoint restrito a chaves de API.' });
|
if (!req.user.is_api_key) return res.status(403).json({ error: 'Endpoint restrito a chaves de API.' });
|
||||||
try {
|
try {
|
||||||
const [origins] = await pool.query('SELECT name FROM origins WHERE tenant_id = ? ORDER BY created_at ASC', [req.user.tenant_id]);
|
const [groups] = await pool.query('SELECT id, name FROM origin_groups WHERE tenant_id = ?', [req.user.tenant_id]);
|
||||||
res.json(origins.map(o => o.name));
|
if (groups.length === 0) return res.json([]);
|
||||||
|
|
||||||
|
const [items] = await pool.query('SELECT origin_group_id, name FROM origin_items WHERE origin_group_id IN (?) ORDER BY created_at ASC', [groups.map(g => g.id)]);
|
||||||
|
const [teams] = await pool.query('SELECT id as team_id, name as team_name, origin_group_id FROM teams WHERE tenant_id = ? AND origin_group_id IS NOT NULL', [req.user.tenant_id]);
|
||||||
|
|
||||||
|
const result = groups.map(g => ({
|
||||||
|
group_name: g.name,
|
||||||
|
origins: items.filter(i => i.origin_group_id === g.id).map(i => i.name),
|
||||||
|
assigned_teams: teams.filter(t => t.origin_group_id === g.id).map(t => ({ id: t.team_id, name: t.team_name }))
|
||||||
|
}));
|
||||||
|
|
||||||
|
res.json(result);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
res.status(500).json({ error: error.message });
|
res.status(500).json({ error: error.message });
|
||||||
}
|
}
|
||||||
@@ -1301,7 +1313,7 @@ apiRouter.get('/teams', async (req, res) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
apiRouter.post('/teams', requireRole(['admin', 'owner', 'super_admin']), async (req, res) => {
|
apiRouter.post('/teams', requireRole(['admin', 'super_admin']), async (req, res) => {
|
||||||
const { name, description, tenantId } = req.body;
|
const { name, description, tenantId } = req.body;
|
||||||
const effectiveTenantId = req.user.role === 'super_admin' ? tenantId : req.user.tenant_id;
|
const effectiveTenantId = req.user.role === 'super_admin' ? tenantId : req.user.tenant_id;
|
||||||
try {
|
try {
|
||||||
@@ -1317,7 +1329,7 @@ apiRouter.post('/teams', requireRole(['admin', 'owner', 'super_admin']), async (
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
apiRouter.put('/teams/:id', requireRole(['admin', 'owner', 'super_admin']), async (req, res) => {
|
apiRouter.put('/teams/:id', requireRole(['admin', 'super_admin']), async (req, res) => {
|
||||||
const { name, description } = req.body;
|
const { name, description } = req.body;
|
||||||
try {
|
try {
|
||||||
const [existing] = await pool.query('SELECT tenant_id FROM teams WHERE id = ?', [req.params.id]);
|
const [existing] = await pool.query('SELECT tenant_id FROM teams WHERE id = ?', [req.params.id]);
|
||||||
@@ -1337,7 +1349,7 @@ apiRouter.put('/teams/:id', requireRole(['admin', 'owner', 'super_admin']), asyn
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
apiRouter.delete('/teams/:id', requireRole(['admin', 'owner', 'super_admin']), async (req, res) => {
|
apiRouter.delete('/teams/:id', requireRole(['admin', 'super_admin']), async (req, res) => {
|
||||||
try {
|
try {
|
||||||
const [existing] = await pool.query('SELECT tenant_id FROM teams WHERE id = ?', [req.params.id]);
|
const [existing] = await pool.query('SELECT tenant_id FROM teams WHERE id = ?', [req.params.id]);
|
||||||
if (existing.length === 0) return res.status(404).json({ error: 'Not found' });
|
if (existing.length === 0) return res.status(404).json({ error: 'Not found' });
|
||||||
|
|||||||
Reference in New Issue
Block a user