['label' => 'All', 'where' => ''], 'starred' => ['label' => 'Starred', 'icon' => 'fa-star', 'where' => 'c.credential_favorite = 1'], 'otp' => ['label' => 'With 2FA', 'icon' => 'fa-clock', 'where' => "c.credential_otp_secret <> ''"], 'nootp' => ['label' => 'No 2FA', 'icon' => 'fa-unlock', 'where' => "(c.credential_otp_secret IS NULL OR c.credential_otp_secret = '')"], 'due' => ['label' => "Not changed in $rotate_days days", 'icon' => 'fa-history', 'where' => "(c.credential_password_changed_at IS NULL OR c.credential_password_changed_at < NOW() - INTERVAL $rotate_days DAY)"], 'shared' => ['label' => 'Shared', 'icon' => 'fa-share-alt', 'where' => "c.credential_id IN (SELECT item_related_id FROM shared_items WHERE item_type = 'Credential' AND " . shareOpenSql() . ")"], ]; $show = isset($shows[$_GET['show'] ?? '']) ? ($_GET['show'] ?? '') : ''; $show_query = $shows[$show]['where'] ? 'AND ' . $shows[$show]['where'] : ''; // Only these sort - filter_header.php will hand through any lowercase word, and // an unknown column takes the page down with a mysqli exception $sortable_columns = ['credential_name', 'credential_uri', 'credential_password_changed_at', 'credential_accessed_at', 'client_name', 'credential_created_at']; if (!in_array($sort, $sortable_columns, true)) { $sort = 'credential_name'; } $sort_column = $sort === 'client_name' ? 'client_name' : "c.$sort"; $search_query = "AND (c.credential_name LIKE '%$q%' OR c.credential_description LIKE '%$q%' OR c.credential_uri LIKE '%$q%' OR c.credential_uri_2 LIKE '%$q%' OR c.credential_note LIKE '%$q%' OR client_name LIKE '%$q%' OR asset_name LIKE '%$q%' OR contact_name LIKE '%$q%' OR c.credential_id IN (SELECT credential_id FROM credential_tags JOIN tags USING (tag_id) WHERE tag_name LIKE '%$q%'))"; $scope_query = clientScopeSql('credential_client_id'); $sql = mysqli_query( $mysqli, "SELECT SQL_CALC_FOUND_ROWS c.credential_id, c.credential_name, c.credential_description, c.credential_uri, c.credential_uri_2, c.credential_username, c.credential_otp_secret, c.credential_favorite, c.credential_archived_at, c.credential_password_changed_at, c.credential_accessed_at, c.credential_client_id, client_name, contact_id, contact_name, contact_photo, contact_archived_at, asset_id, asset_name, asset_type, asset_archived_at FROM credentials c LEFT JOIN clients ON client_id = credential_client_id LEFT JOIN contacts ON contact_id = credential_contact_id AND contact_client_id = credential_client_id LEFT JOIN assets ON asset_id = credential_asset_id AND asset_client_id = credential_client_id WHERE $archive_query $tag_query $search_query $location_query $show_query $scope_query $client_query ORDER BY c.credential_favorite DESC, $sort_column $order, c.credential_name ASC LIMIT $record_from, $record_to" ); $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()")); $credentials = []; while ($row = mysqli_fetch_assoc($sql)) { $credentials[intval($row['credential_id'])] = $row; } // Tags, links and share links for the whole page at once, not per row $credentials_tags = tagsForRecords('credential', array_keys($credentials)); $credentials_links = credentialLinks(array_keys($credentials)); $credentials_shares = credentialShares(array_keys($credentials)); // How many of each, for the pills - everything in scope, before the pill itself $counts = ['' => 0]; $count_sql = []; foreach ($shows as $key => $s) { $count_sql[] = $key === '' ? 'COUNT(*)' : "COALESCE(SUM({$s['where']}), 0)"; } $row = mysqli_fetch_row(mysqli_query($mysqli, "SELECT " . implode(', ', $count_sql) . " FROM credentials c LEFT JOIN clients ON client_id = credential_client_id LEFT JOIN contacts ON contact_id = credential_contact_id AND contact_client_id = credential_client_id LEFT JOIN assets ON asset_id = credential_asset_id AND asset_client_id = credential_client_id WHERE $archive_query $tag_query $search_query $location_query $scope_query $client_query")); foreach (array_keys($shows) as $i => $key) { $counts[$key] = intval($row[$i]); } $filter_url = function ($changes) use ($client_url) { $params = array_merge($_GET, $changes); unset($params['page']); return '?' . http_build_query(array_filter($params, function ($v) { return $v !== '' && $v !== null; })); }; ?>