Circles, ACLs, etc
Bonfire's boundaries framework provides a flexible way to control user access to specific actions and data. It ensures that users can only see and do what they're authorized to.
You can create custom groups of contacts (circles) and grant them specific permissions to interact with you and your content. They can help you take control of your online presence and ensure that your data is shared only with the people you want.
Boundaries are limits that you set for yourself or others to define what you're comfortable with.
These limits can be physical, like curtains or doors; digital, like sharing settings on social media; in writing, like codes of conduct; emotional, like feeling comfortable to take time for self-care; or mental, like choosing what you pay attention to. In Bonfire, boundaries can help limit the type of interactions that others may have with you or things you post.
Boundaries are important because they help you protect yourself, maintain your autonomy, and communicate your needs and expectations clearly.
Term | Definition |
---|---|
Subject or User | An individual who interacts with the system. |
Circle | A categorization method for users, allowing users to group other users (e.g., colleagues, friends). |
Verb | An action that a user can perform (e.g., read, reply). |
Permission | A value indicating whether an action is allowed (true ), denied (false ), or nil . |
Grant | Links a user or circle with a verb and permission. |
ACL | Access Control List, a collection of grants. Also called "boundary" or "boundary preset" in the app. |
Controlled | Links an object to one or more ACLs, to determine access based on the grants. |
Role | A group of verbs linked to a permission. |
Circles are a way of categorizing users. Each user can have their own set of circles to categorize other users. Circles allow a user to group work colleagues differently from friends for example, and to allow different interactions for users in each circle or limit content visibility on a per-item basis.
Verbs represent actions users can perform, such as reading a post or replying to a message. Each verb has a unique ID and are defined in configuration.
A permission is a decision about whether the action may be performed or not. There are 3 possible values:
true
: yes, the action is allowedfalse
: no, the action is explicitly denied (i.e. never permit)null
/nil
: unknown, the action isn't explicitly allowed (defaults to not allowed)A Grant
links a subject
(user or circle) with a Verb
and a permission. It defines the access rights for a specific user or circle in relation to a particular action.
An Acl
is a list of Grant
s used to define access permissions for objects.
Because a user could be in more than one circle and each circle may have a different permission, when a user attempts an action on an object, the system combines all relevant grants to determine the final permission. This combination prioritizes permissions as follows: false > true > nil
, resulting in:
input | input | result |
---|---|---|
nil |
nil |
nil |
nil |
true |
true |
nil |
false |
false |
true |
nil |
true |
true |
true |
true |
true |
false |
false |
false |
nil |
false |
false |
true |
false |
false |
false |
false |
In simpler terms, a final permission is granted only if the combined result is true
. Think of it as requiring an explicit "yes" for permission, while "no" always takes precedence. Notably, nil
acts as a sort of "weak no," it can be overridden by a true
but not granting access on its own. This approach provides flexibility for implementing features like user blocking (false
is crucial here).
For efficiency, nil
is the assumed default and not stored in the database.
The Controlled
multimixin link an object to one or more ACLs. This allows for applying multiple boundaries to the same object. In case of overlapping permissions, the system combines them following the logic described above.
Roles are groups of verbs associated with permissions. While not stored in the database, they are defined at the configuration level to enhance readability and user experience.
Let's illustrate how boundaries work with a real-world example: planning a surprise party without the birthday girl finding out.
iex> import Bonfire.Me.Fake
iex> organizer = fake_user!()
iex> birthday_girl = fake_user!()
iex> friends = [fake_user!(), fake_user!()]
iex> family = [fake_user!(), fake_user!()]
Organize users into relevant circles (friends and family).
iex> alias Bonfire.Boundaries.Circles
iex> {:ok, friends_circle} = Circles.create(organizer, %{named: %{name: "friends"}})
iex> Circles.add_to_circles(friends, friends_circle)
iex> Circles.is_encircled_by?(List.first(friends), friends_circle)
true
iex> {:ok, family_circle} = Circles.create(organizer, %{named: %{name: "family"}})
iex> Circles.add_to_circles(family, family_circle)
This boundary will control access to the surprise party plans.
iex> alias Bonfire.Boundaries.Acls
iex> {:ok, boundary} = Acls.simple_create(organizer, "Surprise party")
Allow friends to discover, read, and respond to party plans, while family members can also edit details and send invitations.
iex> alias Bonfire.Boundaries.Grants
iex> Grants.grant(friends_circle.id, boundary.id, [:see, :read, :reply], true, current_user: organizer)
iex> Grants.grant(family_circle.id, boundary.id, [:see, :read, :reply, :edit, :invite], true, current_user: organizer)
Prevent the birthday person from accessing any party information.
iex> Grants.grant(birthday_girl.id, boundary.id, [:see, :read], false, current_user: organizer)
iex> alias Bonfire.Posts
iex> {:ok, party_plan} = Posts.publish(
current_user: organizer,
boundary: boundary.id,
post_attrs: %{post_content: %{name: "Surprise party!"}})
iex> Boundaries.can?(List.first(friends).id, :read, party_plan.id)
true
iex> Boundaries.can?(List.first(family).id, :invite, party_plan.id)
true
iex> Boundaries.can?(birthday_girl.id, :see, party_plan.id)
false
iex> Boundaries.load_pointer(party_plan.id, current_user: birthday_girl)
nil
By following these steps, the organizer can effectively manage access to ensure the birthday girl cannot see the party plans, while friends and family can.
Copyright (c) 2020 Bonfire Contributors
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.