Skip to content

Saved view definitions: server-enforced attribute and spatial filters on server-backed layers #1675

Description

@giswqs

Summary

Let a server-backed layer be published as a view: a saved attribute and spatial filter applied on the server, so a recipient sees a defined subset of the data and cannot widen it. Includes the special case where the filter is "only the features you created".

Why

Filtering today is a display decision. A MapLibre filter expression, a where clause in a layer's configuration, a definition query set in the UI — all of them live in the project file, are applied in the client, and are trivially removed by whoever holds the project. That is entirely appropriate for cartography and useless for access control.

The consequence is that the answer to "can I share this dataset but only the part that concerns this partner?" is currently no. The workarounds are to physically extract a copy (which immediately goes stale and multiplies the number of places the data lives) or to not share at all.

Two shapes come up repeatedly:

  • Subset by attribute or extent — one county's records out of a statewide table; this year's out of a decade's; non-sensitive categories only.
  • Only your own features — a field-collection or crowd-reporting workflow where many people write to one table and each should see and edit their own rows, with a supervisor seeing all of them. This is the pattern behind most multi-user data-collection requests, and it is unbuildable today.

Proposal

1. A view definition on server-backed layers

For layers whose data is fetched per request — PostGIS through the sidecar and through martin, and sidecar-backed raster/vector endpoints — allow the layer to reference a named, server-stored view definition:

  • an attribute predicate (a validated where, not raw client SQL);
  • an optional spatial predicate (a bounding box or clip polygon);
  • an optional field list, which is the field-level visibility issue's mechanism.

The definition is stored and applied server-side. The client is told it is looking at a view and what the filter is, so the UI can say so honestly, but changing the client's copy changes nothing.

2. Own-features-only mode

A view definition mode that resolves to "rows whose creator matches the authenticated caller", plus a role that is exempt (supervisor sees everything). This depends on editor tracking to have a creator column at all, and on real sign-in to have an identity to match against — sequence it after both.

3. Where the boundary is

State this in the docs and in the UI: view definitions apply to layers the server serves per request. A local file, an embedded GeoJSON, a COG or PMTiles the browser range-reads directly, or any layer already fully resident in the client cannot be subset this way — for those, the only real answer is to publish a physically derived subset. Do not offer the feature on layer types where it would be theater.

Scope notes

  • Mostly backend/geolibre_server/geolibre_server/app/postgis.py: postgis_read and postgis_write both need to compose the view predicate into every query, and postgis_write must additionally refuse writes that would place a row outside the view.
  • Predicates must be built as parameterized SQL, never string-concatenated from client input. The existing _sanitize_error / _validate_postgis_target care in that module is the standard to match.
  • Needs the per-layer capability set as the place to attach the view reference.
  • For martin-served tiles, the equivalent is a dedicated published function/view rather than a runtime predicate; note the difference rather than pretending one mechanism covers both.

Effort

Wishlist. This is the deepest item in the access-control umbrella and the one most worth getting right slowly.


Part of #1665 (access control umbrella).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    wishlistFeature requests that require significant efforts

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions