I think the code suggests this usage is actually deprecated, but I could be wrong:
Thanks! I’ll refrain from making such calls, then, until we get an official statement one way or the other.
I think there needs to be a big disclaimer on the User Management page that explains that any data retrievable by the anvil.users.get_user()
method is ALWAYS readable on the client side. Essentially, any authenticated user can access all data in and linked from their user row.
This is regardless of the permissions set for the Users table.
Perhaps a starting point:
Security
The built in method anvil.users.get_user()
makes an authenticated server side call to the users
table and returns their row to the client. Because of this, any data stored in, or linked from, the users
table should always be considered accessible by the authenticated user.
Anything that is accessible from anvil.server.get_user()
is always accessible on the client side regardless of the table’s Client code access permission.
When adding columns or linking to other tables from the users
table, consider what you are exposing to a bad actor.
Example:
You are building a messaging app that allows user’s to select friends and also block other users. You setup two additional columns in your users
table for blocked
and friends
that allow multiple linked rows to the users
table.
Our bad actor starts looking at their row and notices the blocked
and friends
fields. Perhaps they can add a user Jeff
to their blocked list and now have access to this examples entire users
table by traversing the linked rows.
Here is the example of data leaking client side:
User Table Data Leakage
Determining Published vs Debug Environments
There seems to be some bad information on how to determine if an environment is running as a debug
environment or published
environment. From the information in the docs as well as the IDE documentation helper:
determining if the code is executed in the published
environment should be app.branch == 'published'
. However, this is only true if:
- You create a
published
branch - You select the
Publish 'published' branch
option- Note: You can not use the
Publish this commit
option
- Note: You can not use the
- You never use the
published
branch for development.
This matches the documentation in production-vs-development (looks like maybe a legacy page?):
if app.branch != 'published': print("Dev version of the app has been accessed")
which is also wrong in most cases.
The documentation in Environments and Code is different and may need some additional information added for non-business versions which seem to use Published
rather than Production
in app.environment.name
. But someone would need to verify that as I’m not on a business account (yet).
Hi @racersmith,
The production-vs-development page you’ve linked to is part of the Classic Editor docs and so is not valid for the new Editor. The Classic Editor will be deprecated soon and those docs will go away too, which should hopefully remove some confusion. I will add an issue internally to make the Environments and Code page more clear.
Please redesign the search engine for the documentation.
I knew that searching the documentation for words with an underscore like in_designer
doesn’t work, which is a pretty big problem when you deal with software APIs.
I now found out that searching for normal English words that appear in the title doesn’t work either. For example, searching for custom components
doesn’t find this page that has the two words in the title and it’s the main documentation for custom components: Creating Custom Components
Also, searching the “Need help? Find answers here” from the Help page inside an app and the field inside the docs page need a filter to search for type of content.
More often than not I see myself scrolling down the results a lot so I can find the answer I want because pages for API, Blog or Tutorial keep getting precedence instead of Docs or Forum.
[Minor] Model Classes
Table name
In the To Do example in the Create Model Classes page, the server module code uses app_tables.todos.search(...
rather than app_tables.todo_items.search(...
from . import Module1
class TodoItem(Module1.TodoItem):
@server_method(require_user=True)
@classmethod
def get_my_todos(cls):
me = anvil.users.get_user()
- return app_tables.todos.search(assigned_user=me)
^^^^^
+ return app_tables.todo_items.search(assigned_user=me)
Method name
On the Making a model client-writable page,
- ... you’ll want to override `do_update()` to check ...
^
+ ... you’ll want to override `_do_update()` to check ...
(self, …) to (row, …)?
With how Model Classes work, I wonder if using row
rather than self
would make usage more clear?
Throws a missing column error:
self._last_value = 123
… Odd
row._last_value = 123
… Duh
@server_method
is required for:
self.datetime = now
… What, why?
row.datetime = now
… Client does not have permission to write to tables.
self['datetime']
… What Tomfoolery is this?
row['datetime']
… Did not bat an eye
class TodoItem(app_tables.todo_items.Row):
@property
def is_overdue(self):
return datetime.now() > self["due_date"]
vs.
class TodoItem(app_tables.todo_items.Row):
@property
def is_overdue(row):
return datetime.now() > row["due_date"]
Nothing looks concerning here at first glance:
class TodoItem(app_tables.todo_items.Row, attrs=True):
@anvil.server.server_method
def enable_magic(self):
self.magic = True
While if I got an error here about magic
not being a column, it makes sense:
class TodoItem(app_tables.todo_items.Row, attrs=True):
@anvil.server.server_method
def enable_magic(row):
row.magic = True
What do smarter people think?