Partially-writable Data Table Rows w/ Column-based Access Controls

Location: Data > Table > Form Access Option & Table Column Header
Based on @meredydd’s post: Partially-writable Data Table rows

Essentially, this code allows the developer to return a table row to the client that is “partially writable”. In other words, the row has some cells that can be written to client-side, while other cells cannot. This is extremely useful, and I believe this should be an option inside of every Data Table!

But Jacob, How?

Well, I don’t actually know how, but I do know how I would use it.

In every table’s “Form access” drop-down, we have these options:

  • No Access
  • Can search table
  • Can search, edit and delete

First, add an option below all the others called “Custom I/O”, “Custom Privileges”, “Partial Access”, or maybe something like “Custom Access”. I’ll call it that from now on. This would essentially allow the developer to set column-based access controls. That is, some cells could be set client-side and the table would update automagically, while other cells would be restricted and throw an error.

Currently, when a developer right-clicks any column’s header label, they see these options:

  • Insert Column > (Options)
  • Delete Column

Add another option to the column’s popup menu called:

  • Form Access > (Options).

Within a column’s Form Access drop-down, add these options:

  • No Access (hidden from client; keep reading…)
  • Readable
  • Writable

Notice how these options mirror anvil’s current table structure’s Form options… This Form Access column pop-up menu option would only be visible if the table’s Form access drop-down is set to “Custom Access”.
That’s really all there is to implementing @meredydd’s example into the table editor UI.

The Meat and Bones

So, now, the developer can serve a partially-writable row to the client. Each cell of that partially writable row has an independent I/O privilege which mirrors the row’s table’s column’s privilege. Here’s where things get crazy. What happens if the developer tries to search a row from the client-side (not from server) from a table with Form Access set to Custom Access? Well, the client will definitely receive a table row(s), of course, but any cell within a column in the table that has Form Access: No Access selected will be withheld. That is, client-side access of a partially writable row will only return Readable and Writable cells of that row.
“Much Wow!” - Doge

# Take this Users table for example...
------------------------------------------
| Users | Name | Phone | Email | Address |
------------------------------------------
| empty | Dobb | 72393 | email | 12 W St |
------------------------------------------
| empty | Suze | 43928 | gmail | 42 N Rd |
------------------------------------------

Phone, Email columns are set to No Access. Name column is set to Readable. Address column is set to Writable. Now, within client-side code, the developer can search names, or the user can directly overwrite their address without the developer needing to write a server function and call it.

# pretend this is all client-side code...
print(app_tables.users.list_columns())
>>> ['Name', 'Address'] # All No Access columns excluded from return! :o
print(app_tables.users.search())
>>> [['Dobb', '12 W St'], ['Suze', '42 N Rd']] # example structure
row = app_tables.users.get(name='Dobb')
row['Address'] = '42 N Rd' # I see you, Dobb...
print(print(app_tables.users.search())
>>> [['Dobb', '42 N Rd'], ['Suze', '42 N Rd']] # example structure
row['Name'] = 'Dobby'
>>> Error: Read-only column cannot be changed by client-side code.

All of this functionality changes nothing with how table rows are delivered or searched using server code. This has everything to do with client-side access of table rows on a column-by-column basis. Regardless of whether said row was delivered by server code with strict access controls, such as anvil.users.get_user(), or if said row was accessed directly from client-side code…

IF said row’s table’s Form access option is set to Custom Access, and:

  • If a cell’s column is set to No Access, it will never be returned directly to client-side code.
  • If a cell’s column is set to Readable, it can be seen, but not written to, from client-side code.
  • If a cell’s column is set to Writable, it can be seen and written to directly from client-side code.

~Mind-explosions~

P.S. Custom Access should be called Column-based.
To Anvil, with love.

This could be accomplished with a library (layer over existing functionality). But then a malicious Client user could simply bypass it, by calling the underlying Anvil functions directly.