Hi! We are currently working on a project where every field worker is supposed to see only the features they created. Does anyone have experience with similar requirements?
What we considered:
Every user gets their own database user and pg_service. This would probably be the safest and most robust method, but would produce a large administrative overhead.
Every user gets a separate project. Similar to the option above, but shifts the admin work from DB to QGIS.
Rule-based Symbology. Users will only see their points on the map, but will be able to see and select others’ features in the feature list.
The Provider Feature Filter doesn’t support expression variables.
QField Sync’s layer permissions only support addition, editing, and deletion (not visibility).
(We’re fine with the fact that data exists locally and could technically be read. That’s not a concern for this project.)
Since “security” of the data isn’t a priority, maybe you can add a Variable on each user’s QField and read the value of that variable automatically to identify each one?
I’m talking about the QField Settings > Variables menu. Maybe add something like “user_name”, or just use some of the variables already there, like cloud_useremail.
Our issue isn’t so much with the user identification, but hiding the features, since we couldn’t figure out a way to limit what users are shown based on a variable.
I was thinking of using the value of that Global Variable to compare with a field in your data. For example, by adding a column named “surveyed_by” that is hidden in the form and is auto-populated by QField using the value of the Global Variable (user_name for example).
Then make some filter on the layer showing that data, something like:
"surveyed_by" = @user_name
In other words, something similar to these two you’ve mentioned:
But I’m not sure what you mean by “The Provider Feature Filter doesn’t support expression variables”?
For Postgres layers at least, it’s not possible to save the Provider Feature Filter when using an expression variable
Is there another way to set this up?
oh dang! I get it now , I was not aware of this limitation. Makes sense in regards that the Postgres DB probably has no knowledge of your QGIS environment.
Maybe you can get all the layer and make the filter “locally”? For example, by doing it on the Symbology tab (something similar to what is show on this tutorial) or on Layer panel > right click on layer > Filter… . I expect that those contexts might have access to the variables like @cloud_username .
Using rule-based symbology works for map display, meaning users can only select their own features on the map, but it will sadly still show all features when you select a layer and show its feature list.
Your second recommendation, I did not try before! But this seems to be a shortcut for what we tried before, as it also won’t let me save
I think a reason might be that QFC, when packaging offline layers, writes the data into a geopackage anyway, so using local variables in the DB query wouldn’t make sense…
With the 4.2 changes to project plugins within an org being automatically trusted (which means users shouldn’t be able to disable them if I understand it correctly), a plugin, while overkill in my opinion, might be the only solution for us
Thank you for your ideas tho!
Unless someone finds a cleaner solution, I’ll share the project plugin here once I get it to work.
I’ve just tried with a temporary scratch layer (I don’t have access to a Postgres layer), but Using the Filter... looks pretty similar to your Provider Filter but not identical:
More importantly, on the expression box it mentions a “QGIS expression” instead of a “PostgreSQL WHERE clause”. Maybe this is only because I’m using a local layer, but it’s worth to check it out.
dang it! what about these solutions on StackExchange? basically, it seems like you can encapsulate the variable name inside a var() function to pass it to Postgres.
EDIT: I’ve tested this var('variable_name') method with my local layer and it works. So I believe there is a chance that the filter keeps working even if the layer is converted to a local one.
I believe that would work when creating virtual layers, but I don’t think it’s possible to make virtual layers that don’t directly access the data source (so no offline editing)
Using a filter has another problem in this use case. The filter is also active on the QGIS project, but the QGIS project on your local pc has no variable cloud_username. So the filter, if it works at all, will return zero results.
So you won’t be able to see the data in the office. And worse, if you upload the data file from your office pc to the cloud, all features will be deleted, since the filter on the layer is active and it will upload an ‘empty’ layer.
I did not think of this until I also started trying using the provider filter…
I think this is a bug or missing implementation:
When you long press on the layer in QField it says Show visible features only (at least it does for me). And then it shows all features, which is unexpected. Compare this to QGIS where the Open Attribute Table button also has an option to only show Visible features. This indeed only shows the visible features in your attribute table.
In the QGIS layer properties, the QField tab offers four options for controlling editing permissions. Variables such as @cloud_username can also be used here. It would be very helpful and useful to have two additional options: 1. “Disable display of features on the map” and 2. “Disable display of features in the feature list.”
@tbauer , if you’re dealing with a ‘friendly’ environment (i.e. it’s about being user friendly vs. actually preventing data access), you could use a project plugin and use vector layers’ subsetString property to add a SQL filter at project load.
It’s not an actual QGIS expression, so expression variables such as @cloud_username would not be accessible but you could easily grab that using something like: