v0.9.39 bugs fixes
This commit is contained in:
@@ -10,7 +10,7 @@
|
||||
PROJECT_NAME=jama
|
||||
|
||||
# Image version to run (set by build.sh, or use 'latest')
|
||||
JAMA_VERSION=0.9.38
|
||||
JAMA_VERSION=0.9.40
|
||||
|
||||
# App port — the host port Docker maps to the container
|
||||
PORT=3000
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "jama-backend",
|
||||
"version": "0.9.38",
|
||||
"version": "0.9.40",
|
||||
"description": "TeamChat backend server",
|
||||
"main": "src/index.js",
|
||||
"scripts": {
|
||||
|
||||
@@ -43,6 +43,24 @@ function adminMiddleware(req, res, next) {
|
||||
next();
|
||||
}
|
||||
|
||||
// Allows admins OR members of groups designated as Group Managers or Schedule Managers
|
||||
function teamManagerMiddleware(req, res, next) {
|
||||
if (req.user?.role === 'admin') return next();
|
||||
const db = getDb();
|
||||
const gmSetting = db.prepare("SELECT value FROM settings WHERE key = 'team_group_managers'").get();
|
||||
const smSetting = db.prepare("SELECT value FROM settings WHERE key = 'team_schedule_managers'").get();
|
||||
const allowedGroupIds = [
|
||||
...JSON.parse(gmSetting?.value || '[]'),
|
||||
...JSON.parse(smSetting?.value || '[]'),
|
||||
];
|
||||
if (allowedGroupIds.length === 0) return res.status(403).json({ error: 'Access denied' });
|
||||
const member = db.prepare(`
|
||||
SELECT 1 FROM user_group_members WHERE user_id = ? AND user_group_id IN (${allowedGroupIds.map(() => '?').join(',')})
|
||||
`).get(req.user.id, ...allowedGroupIds);
|
||||
if (!member) return res.status(403).json({ error: 'Access denied' });
|
||||
next();
|
||||
}
|
||||
|
||||
function generateToken(userId) {
|
||||
return jwt.sign({ id: userId }, JWT_SECRET, { expiresIn: '30d' });
|
||||
}
|
||||
@@ -70,4 +88,4 @@ function clearActiveSession(userId, device) {
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { authMiddleware, adminMiddleware, generateToken, setActiveSession, clearActiveSession, getDeviceClass };
|
||||
module.exports = { authMiddleware, adminMiddleware, teamManagerMiddleware, generateToken, setActiveSession, clearActiveSession, getDeviceClass };
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
const express = require('express');
|
||||
const router = express.Router();
|
||||
const { getDb } = require('../models/db');
|
||||
const { authMiddleware, adminMiddleware } = require('../middleware/auth');
|
||||
const { authMiddleware, adminMiddleware, teamManagerMiddleware } = require('../middleware/auth');
|
||||
|
||||
module.exports = function(io) {
|
||||
|
||||
@@ -55,7 +55,7 @@ router.get('/me', authMiddleware, (req, res) => {
|
||||
|
||||
// ── MULTI-GROUP DMs — must come before /:id ───────────────────────────────────
|
||||
|
||||
router.get('/multigroup', authMiddleware, adminMiddleware, (req, res) => {
|
||||
router.get('/multigroup', authMiddleware, teamManagerMiddleware, (req, res) => {
|
||||
const db = getDb();
|
||||
const dms = db.prepare(`
|
||||
SELECT mgd.*,
|
||||
@@ -166,7 +166,7 @@ router.delete('/multigroup/:id', authMiddleware, adminMiddleware, (req, res) =>
|
||||
|
||||
// ── USER GROUPS ───────────────────────────────────────────────────────────────
|
||||
|
||||
router.get('/', authMiddleware, adminMiddleware, (req, res) => {
|
||||
router.get('/', authMiddleware, teamManagerMiddleware, (req, res) => {
|
||||
const db = getDb();
|
||||
const groups = db.prepare(`
|
||||
SELECT ug.*,
|
||||
@@ -176,7 +176,7 @@ router.get('/', authMiddleware, adminMiddleware, (req, res) => {
|
||||
res.json({ groups });
|
||||
});
|
||||
|
||||
router.get('/:id', authMiddleware, adminMiddleware, (req, res) => {
|
||||
router.get('/:id', authMiddleware, teamManagerMiddleware, (req, res) => {
|
||||
const db = getDb();
|
||||
const group = db.prepare('SELECT * FROM user_groups WHERE id = ?').get(req.params.id);
|
||||
if (!group) return res.status(404).json({ error: 'Not found' });
|
||||
@@ -252,13 +252,11 @@ router.patch('/:id', authMiddleware, adminMiddleware, (req, res) => {
|
||||
for (const uid of currentSet) {
|
||||
if (!newIds.has(uid)) {
|
||||
db.prepare('DELETE FROM user_group_members WHERE user_group_id = ? AND user_id = ?').run(ug.id, uid);
|
||||
const stillHasAccess = db.prepare(`SELECT 1 FROM user_group_members ugm WHERE ugm.user_id = ? AND ugm.user_group_id != ? AND EXISTS (SELECT 1 FROM group_members gm WHERE gm.group_id = ? AND gm.user_id = ?)`).get(uid, ug.id, ug.dm_group_id, uid);
|
||||
if (!stillHasAccess) {
|
||||
// For managed DMs, membership is controlled solely by the user group — always remove
|
||||
removeUser(db, ug.dm_group_id, uid, req.user.id);
|
||||
removedUids.push(uid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// For multi-group DMs: add/remove users silently, post group-level notification once
|
||||
const mgDms = db.prepare('SELECT mgd.id, mgd.dm_group_id FROM multi_group_dm_members mgdm JOIN multi_group_dms mgd ON mgd.id = mgdm.multi_group_dm_id WHERE mgdm.user_group_id = ?').all(ug.id);
|
||||
|
||||
2
build.sh
2
build.sh
@@ -13,7 +13,7 @@
|
||||
# ─────────────────────────────────────────────────────────────
|
||||
set -euo pipefail
|
||||
|
||||
VERSION="${1:-0.9.38}"
|
||||
VERSION="${1:-0.9.40}"
|
||||
ACTION="${2:-}"
|
||||
REGISTRY="${REGISTRY:-}"
|
||||
IMAGE_NAME="jama"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "jama-frontend",
|
||||
"version": "0.9.38",
|
||||
"version": "0.9.40",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
Reference in New Issue
Block a user