refactor: replace global WAHA notifications with granular user and group-specific templates and dispatch logic

This commit is contained in:
root
2026-03-30 01:02:23 +07:00
parent 68a764c0df
commit 596a233898
8 changed files with 502 additions and 131 deletions

View File

@@ -28,7 +28,7 @@ if($_SERVER['REQUEST_METHOD'] === 'POST') {
if(isset($_POST['create_password'])) {
$stmt = $pdo->prepare("INSERT INTO passwords (title, username, password, url, notes, owner_id, folder_id, tags) VALUES (?, ?, ?, ?, ?, ?, ?, ?)");
$stmt->execute([$_POST['title'], $_POST['username'], $_POST['password'], $_POST['url'], $_POST['notes'], $user_id, $_POST['folder_id'] ?: null, trim($_POST['tags'] ?? '')]);
notify_waha('Created', 'Password Entry', $_POST['title']);
notify_user($user_id, "You added a new password: " . $_POST['title'], ['action'=>'Created', 'module'=>'Password', 'item'=>$_POST['title']]);
}
if(isset($_POST['update_password'])) {
@@ -36,16 +36,29 @@ if($_SERVER['REQUEST_METHOD'] === 'POST') {
if($p && $p['owner_id'] == $user_id) {
$stmt = $pdo->prepare("UPDATE passwords SET title=?, username=?, password=?, url=?, notes=?, folder_id=?, tags=? WHERE id=? AND owner_id=?");
$stmt->execute([$_POST['title'], $_POST['username'], $_POST['password'], $_POST['url'], $_POST['notes'], $_POST['folder_id'] ?: null, trim($_POST['tags'] ?? ''), $_POST['password_id'], $user_id]);
notify_waha('Updated', 'Password Entry', $_POST['title']);
$ctx = ['action'=>'Updated', 'module'=>'Password', 'item'=>$_POST['title']];
notify_user($user_id, "Password '{$_POST['title']}' updated.", $ctx);
// Notify shared users/groups
$shares = query("SELECT share_type, share_id FROM password_shares WHERE password_id=?", [$_POST['password_id']])->fetchAll();
foreach($shares as $sh) {
if($sh['share_type'] === 'user') notify_user($sh['share_id'], "Shared password '{$_POST['title']}' updated.", $ctx);
else notify_group($sh['share_id'], "Shared group password '{$_POST['title']}' updated.", $ctx);
}
}
}
if(isset($_POST['delete_password'])) {
$p = query("SELECT owner_id, title FROM passwords WHERE id=?", [$_POST['password_id']])->fetch();
if($p && $p['owner_id'] == $user_id) {
$ctx = ['action'=>'Deleted', 'module'=>'Password', 'item'=>$p['title']];
// Notify shared recipients before deletion
$shares = query("SELECT share_type, share_id FROM password_shares WHERE password_id=?", [$_POST['password_id']])->fetchAll();
foreach($shares as $sh) {
if($sh['share_type'] === 'user') notify_user($sh['share_id'], "Shared password '{$p['title']}' has been deleted.", $ctx);
else notify_group($sh['share_id'], "Shared group password '{$p['title']}' has been deleted.", $ctx);
}
query("DELETE FROM passwords WHERE id=? AND owner_id=?", [$_POST['password_id'], $user_id]);
notify_waha('Deleted', 'Password Entry', $p['title']);
}
notify_user($user_id, "Password '{$p['title']}' deleted.", $ctx);
}
// Unshare a specific share record
@@ -76,9 +89,9 @@ if($_SERVER['REQUEST_METHOD'] === 'POST') {
$stmt = $pdo->prepare("INSERT INTO password_shares (password_id, share_type, share_id) VALUES (?, ?, ?)");
$stmt->execute([$p_id, $parts[0], $parts[1]]);
$msg = "A password '{$p['title']}' has been shared with you.";
if($parts[0] === 'user') notify_user($parts[1], $msg);
else notify_group($parts[1], $msg);
notify_waha('Shared', 'Password Entry', $p['title']);
$ctx = ['action'=>'Shared', 'module'=>'Password', 'item'=>$p['title'], 'user'=>$_SESSION['username']??'System'];
if($parts[0] === 'user') notify_user($parts[1], $msg, $ctx);
else notify_group($parts[1], $msg, $ctx);
}
}
}
@@ -365,7 +378,7 @@ $active_folder = $_GET['vault_folder'] ?? 'all';
$favicon = $domain ? "https://www.google.com/s2/favicons?domain={$domain}&sz=32" : '';
$pw_shares = [];
if($p['is_mine']) {
$pw_shares = query("SELECT ps.id, ps.share_type, ps.share_id, u.username, g.name as gname FROM password_shares ps LEFT JOIN users u ON (ps.share_type='user' AND ps.share_id=u.id) LEFT JOIN groups g ON (ps.share_type='group' AND ps.share_id=g.id) WHERE ps.password_id=?", [$p['id']])->fetchAll();
$pw_shares = query("SELECT ps.id, ps.share_type, ps.share_id, u.username, u.profile_pic as upic, g.name as gname, g.profile_pic as gpic FROM password_shares ps LEFT JOIN users u ON (ps.share_type='user' AND ps.share_id=u.id) LEFT JOIN groups g ON (ps.share_type='group' AND ps.share_id=g.id) WHERE ps.password_id=?", [$p['id']])->fetchAll();
}
$shares_json = htmlspecialchars(json_encode($pw_shares), ENT_QUOTES, 'UTF-8');
?>
@@ -589,17 +602,26 @@ function renderPasswordShares(jsonShares) {
return;
}
shares.forEach(sh => {
const label = sh.share_type === 'user' ? ('👤 ' + (sh.username || 'User')) : ('👥 ' + (sh.gname || 'Group'));
const pic = sh.share_type === 'user' ? sh.upic : sh.gpic;
const name = sh.share_type === 'user' ? (sh.username || 'User') : (sh.gname || 'Group');
const chip = document.createElement('div');
chip.style.display = 'inline-flex';
chip.style.alignItems = 'center';
chip.style.gap = '0.35rem';
chip.style.gap = '0.4rem';
chip.style.fontSize = '0.72rem';
chip.style.padding = '3px 7px';
chip.style.padding = '2px 8px 2px 2px';
chip.style.borderRadius = '999px';
chip.style.background = 'rgba(var(--primary-rgb),0.12)';
chip.style.background = 'rgba(var(--primary-rgb),0.1)';
chip.style.color = 'var(--primary)';
chip.innerHTML = `<span>${label}</span><button type="button" style="border:none;background:transparent;color:inherit;cursor:pointer;line-height:1;" title="Unshare" onclick="removePasswordShare(${Number(sh.id)})">×</button>`;
chip.style.border = '1px solid rgba(var(--primary-rgb),0.2)';
let avatarHtml = `<div style="width:20px; height:20px; border-radius:50%; background:var(--primary); color:white; display:flex; align-items:center; justify-content:center; font-size:0.6rem; font-weight:700; overflow:hidden;">${name.charAt(0).toUpperCase()}</div>`;
if(pic) {
avatarHtml = `<img src="${pic}" style="width:20px; height:20px; border-radius:50%; object-fit:cover;">`;
}
chip.innerHTML = `${avatarHtml}<span style="font-weight:600;">${name}</span><button type="button" style="border:none;background:transparent;color:inherit;cursor:pointer;line-height:1;margin-left:2px;font-size:0.9rem;" title="Unshare" onclick="removePasswordShare(${Number(sh.id)})">×</button>`;
list.appendChild(chip);
});
sec.style.display = 'block';