exec("ALTER TABLE passwords ADD COLUMN folder_id INTEGER DEFAULT NULL"); } catch(Exception $e) {} try { $pdo->exec("CREATE TABLE IF NOT EXISTS password_folders ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, owner_id INTEGER, FOREIGN KEY (owner_id) REFERENCES users(id) ON DELETE CASCADE )"); } catch(Exception $e) {} // ── Handle POST ─────────────────────────────────────────────────────────────── if($_SERVER['REQUEST_METHOD'] === 'POST') { if(isset($_POST['create_folder'])) { $stmt = $pdo->prepare("INSERT INTO password_folders (name, owner_id) VALUES (?, ?)"); $stmt->execute([$_POST['folder_name'], $user_id]); } if(isset($_POST['delete_folder'])) { // Move items to no folder $pdo->prepare("UPDATE passwords SET folder_id=NULL WHERE folder_id=? AND owner_id=?")->execute([$_POST['folder_id'], $user_id]); $pdo->prepare("DELETE FROM password_folders WHERE id=? AND owner_id=?")->execute([$_POST['folder_id'], $user_id]); } if(isset($_POST['create_password'])) { $stmt = $pdo->prepare("INSERT INTO passwords (title, username, password, url, notes, owner_id, folder_id) VALUES (?, ?, ?, ?, ?, ?, ?)"); $stmt->execute([$_POST['title'], $_POST['username'], $_POST['password'], $_POST['url'], $_POST['notes'], $user_id, $_POST['folder_id'] ?: null]); } if(isset($_POST['update_password'])) { $p = query("SELECT owner_id FROM passwords WHERE id=?", [$_POST['password_id']])->fetch(); if($p && $p['owner_id'] == $user_id) { $stmt = $pdo->prepare("UPDATE passwords SET title=?, username=?, password=?, url=?, notes=?, folder_id=? WHERE id=? AND owner_id=?"); $stmt->execute([$_POST['title'], $_POST['username'], $_POST['password'], $_POST['url'], $_POST['notes'], $_POST['folder_id'] ?: null, $_POST['password_id'], $user_id]); } } if(isset($_POST['delete_password'])) { $p = query("SELECT owner_id FROM passwords WHERE id=?", [$_POST['password_id']])->fetch(); if($p && $p['owner_id'] == $user_id) { query("DELETE FROM passwords WHERE id=? AND owner_id=?", [$_POST['password_id'], $user_id]); } } if(isset($_POST['bulk_action']) && isset($_POST['selected_passwords'])) { $selected = $_POST['selected_passwords']; $action = $_POST['bulk_action']; if($action === 'delete') { foreach($selected as $p_id) { $p = query("SELECT owner_id FROM passwords WHERE id=?", [$p_id])->fetch(); if($p && $p['owner_id']==$user_id) query("DELETE FROM passwords WHERE id=?", [$p_id]); } } elseif($action === 'share') { $share_target = $_POST['share_target']; $parts = explode('_', $share_target, 2); if(count($parts)===2) { foreach($selected as $p_id) { $p = query("SELECT owner_id, title FROM passwords WHERE id=?", [$p_id])->fetch(); if($p && $p['owner_id']==$user_id) { $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); } } } } elseif($action === 'move_folder' && isset($_POST['move_folder_target'])) { $fid = $_POST['move_folder_target'] ?: null; foreach($selected as $p_id) { $p = query("SELECT owner_id FROM passwords WHERE id=?", [$p_id])->fetch(); if($p && $p['owner_id']==$user_id) { $pdo->prepare("UPDATE passwords SET folder_id=? WHERE id=?")->execute([$fid, $p_id]); } } } } } // ── Fetch ───────────────────────────────────────────────────────────────────── $user_groups = get_user_groups($user_id); $my_group_ids = array_column($user_groups, 'id'); $group_in = implode(',', array_fill(0, count($my_group_ids), '?')) ?: '0'; $params = array_merge([$user_id, $user_id, $user_id], $my_group_ids); $sql = "SELECT p.*, (p.owner_id = ?) as is_mine, pf.name as folder_name FROM passwords p LEFT JOIN password_shares ps ON p.id = ps.password_id LEFT JOIN password_folders pf ON p.folder_id = pf.id WHERE p.owner_id = ? OR (ps.share_type='user' AND ps.share_id = ?) OR (ps.share_type='group' AND ps.share_id IN ($group_in)) GROUP BY p.id ORDER BY pf.name ASC, p.title ASC"; $stmt = $pdo->prepare($sql); $stmt->execute($params); $passwords = $stmt->fetchAll(); // Folder list (own folders only) $folders = query("SELECT * FROM password_folders WHERE owner_id=? ORDER BY name", [$user_id])->fetchAll(); $all_users = query("SELECT id, username FROM users WHERE id != ?", [$user_id])->fetchAll(); $all_groups = query("SELECT * FROM groups")->fetchAll(); // Group passwords by folder $grouped = ['__none__' => []]; foreach($folders as $f) $grouped[$f['id']] = []; foreach($passwords as $p) { $fk = $p['folder_id'] ?? '__none__'; if(!isset($grouped[$fk])) $grouped[$fk] = []; $grouped[$fk][] = $p; } // Active folder filter $active_folder = $_GET['vault_folder'] ?? 'all'; ?>