Authorization
Authorization in MACHHUB is built from three concepts:
- Feature — a resource or capability, e.g.
"collections","users","flows". - Action —
"read","read-write", or any custom string. - Scope —
"all"(everything in the domain),"self"(own data), or any custom scope defined for the domain. A permission has no scopes by default — scopes are added per domain on the console’s Permissions page. - Group — a named set of users that share a set of permissions.
All of these are reached through sdk.auth. You must be authenticated first — see
Authentication.
Checking permissions
Section titled “Checking permissions”Check a single permission
Section titled “Check a single permission”// Returns { permission: boolean }const { permission } = await sdk.auth.checkPermission( 'collections', // feature 'read', // action: 'read' | 'read-write' | custom 'all' // scope: 'all' | 'self' | custom);
if (permission) { // User has access}Signature: checkPermission(feature: string, action: string, scope: string): Promise<PermissionResponse>
Get all allowed actions for a feature
Section titled “Get all allowed actions for a feature”// Returns { actions: string[] }const { actions } = await sdk.auth.checkAction('collections', 'all');// e.g. actions = ['read', 'read-write']Signature: checkAction(feature: string, scope: string): Promise<ActionResponse>
List all permissions in the domain
Section titled “List all permissions in the domain”// Returns Feature[] — every permission defined across all groups in the domainconst permissions = await sdk.auth.getPermissions();// e.g. [{ name: 'collections', action: 'read-write', scope: 'all' }, ...]Signature: getPermissions(): Promise<Feature[]>
The Feature shape
Section titled “The Feature shape”import type { Feature } from '@machhub-dev/sdk-ts';
const feature: Feature = { name: 'collections', // a feature name (see the table below) action: 'read-write', // 'read' | 'read-write' | custom scope: 'all' // a scope defined for the domain (e.g. 'all', 'self', custom)};Group management
Section titled “Group management”Get all groups
Section titled “Get all groups”const groups = await sdk.auth.getGroups();// Each group: { id, name, features: [{ name, action, scope, domain }], user_ids }Create a group
Section titled “Create a group”import type { Feature } from '@machhub-dev/sdk-ts';
const features: Feature[] = [ { name: 'collections', action: 'read', scope: 'all' },];
const group = await sdk.auth.createGroup('Editors', features);// Returns: { id, name, ... }Signature: createGroup(name: string, features: Feature[]): Promise<Group>
Add permissions to a group
Section titled “Add permissions to a group”Each permission entry must use a scope defined for the domain (e.g. "all", "self",
or a custom one). A domain has no scopes until you add them.
import type { Feature } from '@machhub-dev/sdk-ts';
const permissions: Feature[] = [ { name: 'collections', action: 'read-write', scope: 'all' }, { name: 'flows', action: 'read', scope: 'all' }, { name: 'api_keys', action: 'read-write', scope: 'self' },];
await sdk.auth.addPermissionsToGroup(groupId, permissions);Signature: addPermissionsToGroup(group_id: string, permissions: Feature[]): Promise<ActionResponse>
Add a user to a group
Section titled “Add a user to a group”await sdk.auth.addUserToGroup(userId, groupId);Signature: addUserToGroup(userId: string, groupId: string): Promise<ActionResponse>
User management
Section titled “User management”// List all usersconst users = await sdk.auth.getUsers();
// Get a user by idconst user = await sdk.auth.getUserById(userId);
// Create a userawait sdk.auth.createUser( 'Jane', // firstName 'Smith', // lastName 'janesmith', // username 'jane@example.com', // email 'securePassword123', // password '+60123456789', // phone number null // userImage (base64 string or null));Signature: createUser(firstName, lastName, username, email, password, number, userImage): Promise<User>
Getting the current user’s groups and permissions
Section titled “Getting the current user’s groups and permissions”The current user carries group_ids; cross-reference them against all domain groups to
collect the user’s effective permissions.
import { RecordIDToString } from '@machhub-dev/sdk-ts';
// 1. Get user + their group IDsconst user = await sdk.auth.getCurrentUser();const groupIds = user.group_ids ?? [];
// 2. Get all domain groupsconst allGroups = await sdk.auth.getGroups();
// 3. Filter to the ones this user belongs toconst userGroups = allGroups.filter(group => { if (!group.id) return false; return groupIds.includes(RecordIDToString(group.id));});
// 4. Collect all permissions across the user's groupsconst allPermissions = userGroups.flatMap(g => g.features ?? []);Service and guard patterns
Section titled “Service and guard patterns”Centralize checks in an authorization service and protect routes/UI with a guard, in keeping with the service-layer architecture.
import { getOrInitializeSDK } from './sdk.service';import type { Feature } from '@machhub-dev/sdk-ts';
class AuthorizationService { async canAccess(feature: string, action: string, scope: string): Promise<boolean> { try { const sdk = await getOrInitializeSDK(); const { permission } = await sdk.auth.checkPermission(feature, action, scope); return permission; } catch { return false; } }
async getAllowedActions(feature: string, scope: string): Promise<string[]> { try { const sdk = await getOrInitializeSDK(); const { actions } = await sdk.auth.checkAction(feature, scope); return actions ?? []; } catch { return []; } }
async getDomainPermissions(): Promise<Feature[]> { try { const sdk = await getOrInitializeSDK(); return await sdk.auth.getPermissions(); } catch { return []; } }}
export const authorizationService = new AuthorizationService();import { authorizationService } from '../services/authorization.service';
export async function requirePermission( feature: string, action: string, scope: string, redirectTo = '/unauthorized'): Promise<boolean> { const allowed = await authorizationService.canAccess(feature, action, scope); if (!allowed) { window.location.href = redirectTo; return false; } return true;}
// Usageconst canEdit = await requirePermission('collections', 'read-write', 'all');Built-in feature names
Section titled “Built-in feature names”Use these values for the name field in Feature. You may also use custom feature
names for application-specific permissions.
| Feature name | Description |
|---|---|
applications | Manage applications |
users | Manage user accounts |
groups | Manage groups and permissions |
api_keys | Manage API keys |
upstreams | Manage upstream connections |
collections | Manage data collections |
flows | Node-RED flow management |
historian | Time-series historian data |
processes | Manage processes |
general_settings | General system settings |
gateway | Gateway configuration |
logs | Access system logs |
dashboard | Dashboard access |
integration | Integration management |
manage_namespace | Manage namespaces |
license | License management |
Checklist
Section titled “Checklist”-
checkPermissioncalled before sensitive mutations. -
checkActionused to show/hide UI controls dynamically. -
getPermissionsused to display the domain’s full permission set. -
addPermissionsToGroupuses scopes defined for the domain (e.g.all,self, or custom). -
createGroupavoids the reserved name"Superuser". - Permission checks on route entry, not only on data fetch.
- Review login and sessions in Authentication.
- See the full API surface in the Cheat Sheet.