By default Volt models can be read or edited by anyone, however it is easy to restrict how a model can be read or changed. Volt's permissions API breaks this down in to four different actions: create, read, update, delete (or CRUD)
You specify permissions inside of a model class like so:
class Todo < Volt::Model permissions do # .. permissions logic .. end end
The permissions block is called anytime one of the CRUD actions happens on the model. Inside of the permissiosn block, you can use
deny to restrict permissions If you call either without any arguments, then the entire action is blocked. You can instead pass in a list of field names as arguments, then the action will only be blocked for those fields. When run,
self inside of the permission block will be the current model.
class Todo < Volt::Model permissions do deny :label end end
If the last value in a permissions block (the implicit return) is a Promise, the permissions block will resolve the permissions block before continuing. (So you can query other models inside of permissions blocks, and use .then to return a new promise.
class Todo < Volt::Model permissions do # Volt.current_user returns a promsie that resolves the current user, we # then return a new promise that checks the admin state and denies unless # the user is an admin. Volt.current_user.then do |user| deny unless user.admin? end end end
You can use the
own_by_user method to automatically assign the
user_id field to the logged in user when a model is created (See Users for more info) It will also setup a belongs_to :user (or optionally another key passed in for the
If a model is owned by the user, you can check if the currently logged in user is the owner in a permissions block by calling
.owner? Owner will return true if the current user is the owner.
class Todo < Volt::Model own_by_user permissions do deny unless owner? end end
^ The above would prevent anyone besides the owner from reading, creating, updating, or deleting this model. (
.owner? returns true in create because
own_by_user will have already assigned the
Once one allow is specified, all other fields will be denied. Deny's override allow's.
class Todo < Volt::Model permissions do allow :label, :complete end end
^ only label and complete would be allowed, all others would be blocked. Using
permission without any arguments will setup permissions for all CRUD operations (create, read, update, delete) To restrict the permissions to only certain actions, you can pass in symbol's for each action as arguments to the
permissions method. You can also specify multiple permission blocks.
class Todo < Volt::Model permissions(:create, :update) do deny :notes, :secret_notes unless owner? end permissions(:read) do deny :secret_notes unless owner? end permissions(:delete) do deny unless owner? end end
^ The above would allow only the owner to change
secret_notes, but anyone can change the other fields. Only the owner could read
secret_notes (while all other fields would be able to be read by anyone). And only the owner could delete the model.
You can also pass an action argument to the permission block. This will be a symbol representing the current action that is running.
class Todo < Volt::Model permissions(:read, :update) do |action| if action == :read allow else deny unless owner? end end end
Sometimes rather than setting up complex logic in permissions, you can simply deny changes, then only do changes from a task. For example, if you wanted to set an
admin flag on the user model. You could simply deny updates to
admin and then manually set admin by skipping permissions.
class User < Volt::User permissions(:create, :update) do # make it so no one can update without skipping permissions deny :admin end end
You can skip permissions by running
Volt.skip_permissions and passing it a block.
skip_permissions can only be run on the server, for obvious reasons.
Volt.skip_permissions do # Running without permission checks. # Set admin user._admin = true end
The permissions API attempts to provide a simple way to define who can do what to your app's data. You can put any logic inside of the permissions blocks