v0.9.43 user group dm permissions fixed

This commit is contained in:
2026-03-16 19:14:04 -04:00
parent ee4bb4b86d
commit 177c05d7da
5 changed files with 20 additions and 12 deletions

View File

@@ -10,7 +10,7 @@
PROJECT_NAME=jama PROJECT_NAME=jama
# Image version to run (set by build.sh, or use 'latest') # Image version to run (set by build.sh, or use 'latest')
JAMA_VERSION=0.9.42 JAMA_VERSION=0.9.43
# App port — the host port Docker maps to the container # App port — the host port Docker maps to the container
PORT=3000 PORT=3000

View File

@@ -1,6 +1,6 @@
{ {
"name": "jama-backend", "name": "jama-backend",
"version": "0.9.42", "version": "0.9.43",
"description": "TeamChat backend server", "description": "TeamChat backend server",
"main": "src/index.js", "main": "src/index.js",
"scripts": { "scripts": {

View File

@@ -13,7 +13,7 @@
# ───────────────────────────────────────────────────────────── # ─────────────────────────────────────────────────────────────
set -euo pipefail set -euo pipefail
VERSION="${1:-0.9.42}" VERSION="${1:-0.9.43}"
ACTION="${2:-}" ACTION="${2:-}"
REGISTRY="${REGISTRY:-}" REGISTRY="${REGISTRY:-}"
IMAGE_NAME="jama" IMAGE_NAME="jama"

View File

@@ -1,6 +1,6 @@
{ {
"name": "jama-frontend", "name": "jama-frontend",
"version": "0.9.42", "version": "0.9.43",
"private": true, "private": true,
"scripts": { "scripts": {
"dev": "vite", "dev": "vite",

View File

@@ -17,10 +17,11 @@ export default function GroupInfoModal({ group, onClose, onUpdated, onBack }) {
const [savingCustom, setSavingCustom] = useState(false); const [savingCustom, setSavingCustom] = useState(false);
const isDirect = !!group.is_direct; const isDirect = !!group.is_direct;
const isManaged = !!group.is_managed; // UG DM or Multi-Group DM — only editable via Group Manager
const isOwner = group.owner_id === user.id; const isOwner = group.owner_id === user.id;
const isAdmin = user.role === 'admin'; const isAdmin = user.role === 'admin';
const canManage = !isDirect && ((group.type === 'private' && isOwner) || (group.type === 'public' && isAdmin)); const canManage = !isDirect && !isManaged && ((group.type === 'private' && isOwner) || (group.type === 'public' && isAdmin));
const canRename = !isDirect && !group.is_default && ((group.type === 'public' && isAdmin) || (group.type === 'private' && isOwner)); const canRename = !isDirect && !isManaged && !group.is_default && ((group.type === 'public' && isAdmin) || (group.type === 'private' && isOwner));
useEffect(() => { useEffect(() => {
if (group.type === 'private') { if (group.type === 'private') {
@@ -116,8 +117,8 @@ export default function GroupInfoModal({ group, onClose, onUpdated, onBack }) {
}; };
// For direct messages: only show Delete button (owner = remaining user after other left) // For direct messages: only show Delete button (owner = remaining user after other left)
const canDeleteDirect = isDirect && isOwner; const canDeleteDirect = isDirect && isOwner && !isManaged;
const canDeleteRegular = !isDirect && (isOwner || (isAdmin && group.type === 'public')) && !group.is_default; const canDeleteRegular = !isDirect && !isManaged && (isOwner || (isAdmin && group.type === 'public')) && !group.is_default;
return ( return (
<div className="modal-overlay" onClick={e => e.target === e.currentTarget && onClose()}> <div className="modal-overlay" onClick={e => e.target === e.currentTarget && onClose()}>
@@ -236,16 +237,23 @@ export default function GroupInfoModal({ group, onClose, onUpdated, onBack }) {
{/* Actions */} {/* Actions */}
<div className="flex-col gap-2"> <div className="flex-col gap-2">
{/* Managed group notice */}
{isManaged && (
<div style={{ background: 'var(--surface-variant)', border: '1px solid var(--border)', borderRadius: 'var(--radius)', padding: '10px 14px', fontSize: 13, color: 'var(--text-secondary)', display: 'flex', alignItems: 'center', gap: 8 }}>
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" style={{ flexShrink: 0, color: 'var(--text-tertiary)' }}><circle cx="12" cy="12" r="10"/><line x1="12" y1="8" x2="12" y2="12"/><line x1="12" y1="16" x2="12.01" y2="16"/></svg>
This conversation is managed via the Group Manager tool.
</div>
)}
{/* Direct message: leave (if not already owner/last person) */} {/* Direct message: leave (if not already owner/last person) */}
{isDirect && !isOwner && ( {isDirect && !isManaged && !isOwner && (
<button className="btn btn-secondary w-full" onClick={handleLeave}>Leave Conversation</button> <button className="btn btn-secondary w-full" onClick={handleLeave}>Leave Conversation</button>
)} )}
{/* Regular private: leave if not owner */} {/* Regular private: leave if not owner */}
{!isDirect && group.type === 'private' && !isOwner && ( {!isDirect && !isManaged && group.type === 'private' && !isOwner && (
<button className="btn btn-secondary w-full" onClick={handleLeave}>Leave Group</button> <button className="btn btn-secondary w-full" onClick={handleLeave}>Leave Group</button>
)} )}
{/* Admin take ownership (non-direct only) */} {/* Admin take ownership (non-direct, non-managed only) */}
{!isDirect && isAdmin && group.type === 'private' && !isOwner && ( {!isDirect && !isManaged && isAdmin && group.type === 'private' && !isOwner && (
<button className="btn btn-secondary w-full" onClick={handleTakeOwnership}>Take Ownership (Admin)</button> <button className="btn btn-secondary w-full" onClick={handleTakeOwnership}>Take Ownership (Admin)</button>
)} )}
{/* Delete */} {/* Delete */}