• log out

Just some of Qbix's major features:

More features for advanced users:

There is much more to Qbix...

Standardized access control

One of the main goals of Qbix is to enable developers to deliver experiences that not only delight and engage users, but empower them to have control over their own data.

That is why the Streams plugin contains very powerful and expressive ways to control access. We built it all for you — so users can have a standard interface they expect for managing their streams, and you can focus on building your application.

access control

What users can do

Whether it's their name, relationship status, age, location, or something else, users of Qbix apps can expect to have a standard way to control who can access the streams they publish. There are three different aspects, each with their own levels:

  • Read level - This determines who can see the messages posted to the stream. Those with the lowest read level (namely 0) can't even see the stream exists.
  • Write level - This determines who can edit the stream. Those with the lowest write level can't affect the stream. Higher levels allow posting messages, voting for relations to other streams, and more.
  • Admin level - The publisher of the stream can assign admins to manage the stream, especially useful if allows multiple writers. Certain levels allow granting higher access to other users or admins using invitations.
  • Permissions - This is for custom permissions, such as registerForMe and highlight.

Publishers and contacts

Besides assigning access levels to individual users, the Streams plugin also supports assigning access to entire contact labels. So Qbix apps can support roles and permissions out of the box, except the roles are actually contact labels assigned by the stream's publisher.

A single app can have thousands or millions of users publishing streams of information, while others subscribe to this information, or join/leave and interact with the streams and with each other, in real time.

In Qbix, users can represent either people or communities. Thus, a person can set access for contact labels such as "friends" or "family", while an organization could set access for "project managers" or "clients".

When user X accesses a stream published by user Y, the system checks whether X is in Y's contacts. The access levels and permissions are aggregated from all the Streams_Access rows with ofContactLabel corresponding to all the labels. However, if X has saved specific access information for Y, through ofUserId, then it overrides any of the aggregated access levels they would have otherwise had.

Inheriting access from other streams

Another powerful feature of the Streams plugin is the ability for a stream to inherit access levels or permissions from other streams. This is configured in the stream's inheritAccess field, which contains a JSON-encoded list of other streams whose access rules should influence the current one.

Each entry in the inheritAccess array has one of several forms:

[
		[publisherId, streamName],
		[publisherId, streamName, [readCap, writeCap, adminCap]],
		[publisherId, streamName, [readCap, writeCap, adminCap], [permission1, permission2]]
	]

The first two values identify the stream to inherit from. Optionally, you can provide caps that limit how much access can be inherited. You can also specify a list of permissions to filter which permissions are imported from the parent stream. If no caps or permission filters are provided, everything the user has in the parent stream is eligible to be inherited.

When a user accesses a stream, the framework loads the stream’s own read, write, admin levels, any applicable invitations, and any increases derived from the fromPermissions configuration. After this, it evaluates the inheritAccess list and attempts to raise the user’s access levels further based on the streams listed there.

Inheritance proceeds one “generation” at a time. The system fetches each parent stream as the current user, looks at the user’s access there, and applies it to the current stream. Caps ensure that inheritance never exceeds what was declared in the configuration. If permission filters were supplied, only those permissions are inherited. In all cases, direct access rules assigned specifically to a user take precedence and are not overridden by inheritance.

Developers can modify the inheritAccess stack using two helper methods. The inheritAccessSet method can add or update inheritance entries, including new caps or permission limits. The inheritAccessUnset method removes inheritance from a given parent stream.

Configuring access from permissions

In addition to assigning access levels directly to users or contact labels, each stream type can now define a fromPermissions configuration. This allows the system to automatically raise a user's read, write, or admin levels based on the permissions they already have in the stream.

The configuration is found under the stream type in your Streams config file. It maps permission names to minimum required levels. For example:

{
		"Streams/topic": {
			"fromPermissions": {
				"moderator": {
					"readLevel": "read",
					"writeLevel": "edit",
					"adminLevel": "manage"
				},
				"vip": {
					"readLevel": "read"
				}
			}
		}
	}

When a user accesses a stream, the framework checks all the permissions they have in that stream. If any of these permissions appear in the fromPermissions map, the system ensures that the user's access levels are at least as high as the levels specified there. In other words, permissions can now serve as a reliable basis for automatically granting higher visibility, editing capability, or administrative control.

This feature integrates seamlessly with invitations, inheritance, and contact labels. The escalation from fromPermissions happens early in the access calculation, before inheriting access from other streams. It does not override negative levels or explicit restrictions, but ensures that users with certain permissions are never granted access below what those permissions imply.

By defining fromPermissions rules, developers can express role-based access logic directly in the stream configuration, rather than duplicating it across application code. This keeps access policies consistent, transparent, and easy to maintain across the entire system.

Testing access

The Streams plugin provides four primary methods for determining whether a user has sufficient access to a stream: testReadLevel, testWriteLevel, testAdminLevel, and testPermission. These methods allow developers to check, at any moment, whether the current user is allowed to read from, write to, administrate, or perform a specific action on the stream.

Each method evaluates the user's access by combining several sources of information:

  • the access levels explicitly stored for that user or contact label
  • any invitations the user has followed (affecting read access only)
  • the fromPermissions configuration defined for that stream type
  • access inherited from other streams via inheritAccess
  • the publisher override (a stream's publisher always has full access)

The goal of the access testing system is to ensure that users cannot obtain more access than intended, while also ensuring that their access is never lower than what their permissions, invitations, or inherited relationships imply.

Configuring access from permissions

Each stream type may define a fromPermissions configuration, which maps permission names to minimum read, write, or admin levels. When a user holds one of these permissions in a stream, the system automatically escalates the user's effective access levels before performing any of the access tests.

{
		"Streams/topic": {
			"access": {
				"fromPermissions": {
					"moderator": {
						"readLevel": "read",
						"writeLevel": "edit",
						"adminLevel": "manage"
					},
					"vip": {
						"readLevel": "read"
					}
				}
			}
		}
	}

When testReadLevel, testWriteLevel, or testAdminLevel is called, the system checks all the permissions the user currently has in the stream. If any of those permissions appear in the fromPermissions configuration, the user's access levels are raised to meet or exceed the minimums specified there. This ensures that permissions can be used to naturally express higher roles within the stream, without having to manually update access levels everywhere.

Effect of invitations

For read access, invitations can also increase a user's read level. If the user follows an invitation to a stream, the read level specified in the invitation acts as a minimum threshold for testReadLevel. This does not affect write or admin access, which remain controlled by the stream's access rules and the fromPermissions configuration.

Integration with inheritance and direct access

Escalation from fromPermissions and invitations occurs before any inheritance logic is applied. After that, the system considers any entries listed in inheritAccess, allowing streams to gain further access from parent streams, subject to caps and direct-source rules. Finally, if a user has direct access assigned to them (for example, through ofUserId), it takes precedence and is never overridden.

By combining access levels, invitations, permission-based escalation, inherited streams, and direct assignments, the access testing functions provide a clear and consistent method for determining what users can and cannot do within any stream in a Qbix app.

Effect of invites on testReadLevel()

When a user follows an invitation link to view a stream, the invitation may grant them a temporary or permanent minimum read level. This affects how testReadLevel() behaves, ensuring that invited users are not blocked from viewing the stream they were explicitly invited to.

Each invitation can include an associated read level. When the user accepts the invitation, the Qbix Platform records that the user has followed the invite, and from that moment onward:

  • testReadLevel(X) will always succeed if X is less than or equal to the read level specified in the invitatio