feat: add saved static and smart camera collections - #501
Open
matteius wants to merge 1 commit into
Open
Conversation
matteius
force-pushed
the
feat/fleet-collections
branch
from
August 22, 2026 16:06
620cbe9 to
bd7eff2
Compare
matteius
force-pushed
the
feat/fleet-collections
branch
from
August 22, 2026 23:15
bd7eff2 to
c1bf468
Compare
matteius
force-pushed
the
feat/fleet-collections
branch
from
August 22, 2026 23:17
c1bf468 to
084ac25
Compare
matteius
force-pushed
the
feat/fleet-collections
branch
from
August 22, 2026 23:24
084ac25 to
8599cae
Compare
matteius
force-pushed
the
feat/fleet-collections
branch
from
August 22, 2026 23:36
8599cae to
b51e9d8
Compare
matteius
force-pushed
the
feat/fleet-collections
branch
2 times, most recently
from
August 23, 2026 00:18
0066654 to
824dc54
Compare
matteius
force-pushed
the
feat/fleet-collections
branch
from
August 23, 2026 00:19
824dc54 to
e629ad4
Compare
Contributor
There was a problem hiding this comment.
Pull request overview
Adds persistent static and smart camera collections with CRUD, membership, previews, visibility controls, RBAC filtering, and selector evaluation.
Changes:
- Adds collection schema, persistence, validation, and atomic membership updates.
- Adds collection APIs, authorization, previews, and route registration.
- Reuses fleet health enrichment and adds documentation and tests.
Reviewed changes
Copilot reviewed 14 out of 14 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Summary | Final review notes |
|---|---|---|
tests/unit/test_db_camera_collections.c |
Database persistence tests | — |
tests/unit/test_api_handlers_camera_collections.c |
API, visibility, RBAC, and preview tests | — |
tests/unit/CMakeLists.txt |
Registers collection tests | — |
src/web/libuv_api_handlers.c |
Registers collection routes | — |
src/web/api_handlers_fleet.c |
Reuses fleet health enrichment | — |
src/web/api_handlers_camera_collections.c |
Implements collection APIs and authorization | Moderate (2 votes): filter or omit raw membership counts; validate UUID shape; handle private creation when authentication is disabled. |
src/database/db_fleet_query.c |
Provides runtime health enrichment | — |
src/database/db_camera_collections.c |
Implements persistence and membership transactions | Critical (1 vote): roll back after a failed COMMIT. |
include/web/api_handlers_camera_collections.h |
Declares collection handlers | — |
include/database/db_fleet_query.h |
Declares health enrichment | — |
include/database/db_embedded_migrations.h |
Embeds migration 0051 | — |
include/database/db_camera_collections.h |
Declares collection database APIs | — |
docs/API.md |
Documents collection endpoints and behavior | — |
db/migrations/0051_add_camera_collections.sql |
Adds collection schema and indexes | — |
Suppressed comments (2)
src/web/api_handlers_camera_collections.c:315
- When authentication is disabled,
httpd_check_viewer_accessreturns the anonymous pseudo-user asUSER_ROLE_VIEWER, even thoughhttpd_check_admin_privilegesgrants that same request admin access. This condition therefore redacts selectors from unauthenticated smart-collection reads and from the POST/PUT response (the added smart-collection test expects the selector object). Include the auth-disabled mode in this privileged check.
bool include_selector = user->role == USER_ROLE_ADMIN ||
(collection->owner_user_id > 0 &&
collection->owner_user_id == user->id);
src/web/api_handlers_camera_collections.c:157
- This evaluates selectors against
db_fleet_camera_loadrecords, but that loader never populatesfleet_camera_t.manufactureror.model(its SELECT has no such fields and the struct is zero-initialized). Therefore valid v1vendorandmodelpredicates always see an empty string and smart collections using them silently match zero cameras. Populate those fields in the shared inventory path or explicitly reject/disable those predicates until inventory data exists.
for (int i = 0; i < camera_count; i++) {
if (fleet_selector_matches(selector, &cameras[i], NULL)) {
matched[matched_count++] = &cameras[i];
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Comment on lines
+73
to
+76
| static bool transaction_finish(sqlite3 *db, bool success) { | ||
| const char *sql = success ? "COMMIT;" : "ROLLBACK;"; | ||
| return sqlite3_exec(db, sql, NULL, NULL, NULL) == SQLITE_OK && success; | ||
| } |
| } else { | ||
| cJSON_AddNullToObject(object, "owner_user_id"); | ||
| } | ||
| cJSON_AddNumberToObject(object, "member_count", collection->member_count); |
Comment on lines
+21
to
+23
| static bool valid_uuid(const char *value) { | ||
| return value && strlen(value) == CAMERA_UUID_STRING_SIZE - 1; | ||
| } |
Comment on lines
+37
to
+39
| return user->role == USER_ROLE_ADMIN || collection->is_shared || | ||
| (collection->owner_user_id > 0 && | ||
| collection->owner_user_id == user->id); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
API
GET|POST /api/camera-collectionsGET|PUT|DELETE /api/camera-collections/{collection_uuid}GET|PUT /api/camera-collections/{collection_uuid}/membersPOST /api/camera-collections/{collection_uuid}/previewAuthorization and safety
Validation
Stack