At Appwrite, we want our products and services to be as simple and flexible as possible. Keeping this in mind, we have decided to enhance our permission system further. Permissions are one of the things that makes Appwrite so powerful. It allows developers to define access to resources in a project at a granular level as a project, which is crucial for many modern applications. However, the existing permissions on Appwrite were a little confusing and limiting, so we decided to iterate and introduce changes. In this article, we will explain the limitations of the existing permissions and how we changed them to make them more flexible and understandable.
In the existing permission system, you can either apply document or collection level permissions, but you can never apply both, making some of the use cases difficult. This was an improvement from our older permissions, where we applied both document-based and collection-based permissions to the same resource. Still, it was confusing to developers how Appwrite handled it.
For example, imagine an app like Reddit, where anyone could create a subreddit; however, only admins could delete it. There's no way of achieving this in the current solution because, as of right now, we only have to write permission which, when allowed, users can both update and delete resources.
Also, with the existing permissions, it was unclear who could create documents. If you applied collection level, whoever has the write permission can create the document. However, if you give someone write permission at the collection level, they can also update and delete all the documents in that collection. That might be dangerous in many cases. With document level permission, you have no control as anyone with a valid session can create documents in the collection.
In order to solve these issues we are making a couple of changes. First, we are going back to using both the collection and document level permissions, but keeping it simple to understand. With the new permission, during the permission check, both the collection and document permissions are checked, and you only need permission at one of the levels to have the desired access. Let's see how we achieve that.
We are introducing the create permission to solve the ambiguity regarding who can create resources. This permission is only available on the collection level, i.e., on collections and buckets (but not documents and files). Though we don't recommend it, we do allow role:all (now any, more in next section) for
create permission so that unauthorized users could create documents, files, or execution if you want to.
We are introducing separate update and delete permissions, so you can provide specific permissions if your project demands it. Not to worry, the write permission will stay as an alias that will couple create, update and delete for collections/buckets and update and delete for documents/files. With this, you can get specific and give only the owner of the document access to update the document but give the admin access to delete the documents.
With this new change, guests can now write i.e. both create, update and delete, resources if you allow in your permissions. Previously this was not possible. In order to make it more secure with guest write, we have an abuse limit set for those endpoints that newly support guest write. With this change you don’t have to force anonymous authentication if you want to allow guests to create resources. For example, you could easily create a contact form in your website and write data to Appwrite when the form is submitted.
We now have permissions like role:member to determine the user's authentication status. If you are familiar with all Appwrite services, you might have noticed that both words role and membership are used with Teams API, not Account/User APIs. The naming convention we have right now is not too straightforward and is not consistent with the rest of Appwrite.
It still works the same way, but way easier to understand and remember.
The permissions are an array of strings, meaning you have to remember the format and possible values yourself. And you cannot use the code completion functionalities of modern IDEs. To overcome this, we have introduced Permission and Role helper classes in each SDK. They are similar to the Query class that you are familiar with. Permission and Role classes provide static methods that will simplify adding permissions, for example.
database.createDocument( ID.custom("articles"), // collectionID ID.unique(), // documentID data, // Document itself [ // permissions Permission.read(Role.any()), Permission.delete(Role.guests()), Permission.read(Role.team('moderators')), Permission.read(Role.team('admins')), Permission.read(Role.team('admins', 'owner')), Permission.delete(Role.user('meldiron')), ] );
The static methods will return the appropriate string in the format required by the API, and you will get excellent auto-completion features of the IDE. You don't have to remember what values are possible and what format the values need to be passed in.
Well, with this refactor, the permission system of Appwrite will be more powerful yet simple to understand and use. We would like to thank everyone who helped us in this refactor by providing feedback on the GitHub discussion.
If there are any issues or confusion, we always welcome feedback. This powerful permission system and the beautiful helper classes in SDKs make it so simple to manage permissions and quickly build applications with advanced permissions for many different use cases. I can't wait to see how you use this new permission system and what you build with it.
To learn more about the new permissions, visit the official permissions documentation. Below are other helpful resources to learn more about Appwrite and get help.