Skip to content

BF user and app-role context

INFO

Before you start First bind the user under Role Management, then use the roles available in the BFF to drive your feature logic. This page only covers how to read the current logged-in user and current app roles inside a BFF script.

1. How to read them in a script

All BFF standalone endpoint scripts share this function signature:

JavaScript
export default async function(params, context) {
  // params: HTTP 请求体
  // context: 运行时上下文
}

Read the current user and app roles from context:

JavaScript
const FINANCE_APPROVER_ROLE_ID = xxx;

export default async function getCurrentUserRoles(params, context) {
  const userInfo = context.userInfo || {};
  const appRoles = context.appRoles || [];

  // 这里直接用脚本内固定的角色 ID 判断。roleId 对应 app_role_permit.id。
  const roleIds = appRoles
    .map(role => role.roleId)
    .filter(roleId => roleId !== null && roleId !== undefined);

  const hasFinanceApproverRole = roleIds.some(
    roleId => Number(roleId) === FINANCE_APPROVER_ROLE_ID
  );

  return {
    appCode: context.appCode,
    tenantCode: context.tenantCode || null,
    userId: userInfo.userId,
    username: userInfo.username,
    userRole: userInfo.role,
    appRoles,
    roleIds,
    hasFinanceApproverRole
  };
}

2. Relevant fields in context

FieldTypeDescription
context.userInfoobjectRuntime user context
context.appRolesarrayApp-role relations enabled for the current user under the current appCode
context.tenantCodestringTenant code of the current logged-in user
context.appCodestringApp code the current BFF execution belongs to
context.clientobjectBFF SDK for data access, SQL, transactions, extensions, and more

3. Structure of appRoles

context.appRoles is a List<Map<String, Object>>.

Each entry contains:

FieldTypeSourceDescription
idnumberuser_app_relation.idPrimary key of the user-app relation
appCodestringuser_app_relation.app_codeApp code
userIdnumberuser_app_relation.user_idUser ID
usernamestringuser_app_relation.usernameUsername
statusstringuser_app_relation.statusUser status in the app; enabled entries have the value ENABLE
roleTypestringuser_app_relation.role_typeRole type, such as ADMIN, DEV, USER, CUSTOM (all custom roles have CUSTOM)
roleIdnumberuser_app_relation.role_idRole configuration ID, referencing app_role_permit.id
roleNamestringapp_role_permit.role_name or the default role descriptionRole name

Example response:

JSON
[
  {
    "id": 1001,
    "appCode": "demo-app",
    "userId": 12345,
    "username": "zhangsan",
    "status": "ENABLE",
    "roleType": "ADMIN",
    "roleId": 10,
    "roleName": "管理员"
  }
]

4. Permission model

The permission model is "permissions bind to roles, users bind to roles":

Plain
用户
  -> user_app_relation
  -> roleType / roleId
  -> app_role_permit
  -> permits
  -> PermissionEngine 判断资源动作权限

In other words:

  • user_app_relation records which roles a user holds in a given app.
  • app_role_permit records which permission configuration a role holds.
  • app_role_permit.permits stores the role's full permission expression.

If your BFF script only needs to check whether the current user is an admin, developer, regular member, or custom role, context.appRoles is all you need.

5. Common snippets

Check for a specific role ID:

JavaScript
function hasRoleId(context, requiredRoleId) {
  const appRoles = context.appRoles || [];
  return appRoles.some(role => Number(role.roleId) === Number(requiredRoleId));
}

Check for any of several role IDs:

JavaScript
function hasAnyRoleId(context, requiredRoleIds) {
  const appRoles = context.appRoles || [];
  const requiredIdSet = new Set((requiredRoleIds || []).map(roleId => Number(roleId)));
  return appRoles.some(role => requiredIdSet.has(Number(role.roleId)));
}

Read basic current-user info:

JavaScript
function getCurrentUser(context) {
  const userInfo = context.userInfo || {};
  return {
    userId: userInfo.userId,
    username: userInfo.username,
    nickname: userInfo.nickname,
    tenantCode: context.tenantCode || userInfo.tenantCode || null
  };
}

Protect a BFF with a role check:

JavaScript
const FINANCE_APPROVER_ROLE_ID = xxx;

export default async function protectedEndpoint(params, context) {
  if (!hasRoleId(context, FINANCE_APPROVER_ROLE_ID)) {
    throw new Error("当前用户无指定角色权限");
  }

  return {
    success: true
  };
}

function hasRoleId(context, requiredRoleId) {
  const appRoles = context.appRoles || [];
  return appRoles.some(role => Number(role.roleId) === Number(requiredRoleId));
}

6. Notes

  • context.appRoles includes only role relations in ENABLE status under the current appCode.
  • A user can hold multiple role relations in the same app, which is why appRoles is an array.
  • Use roleType to check system roles; roleName is better for display or matching custom role names.
  • Never trust user, role, or permission fields submitted by the frontend. Always rely on context.userInfo and context.appRoles.

基于飞书知识库同步生成,内容以飞书源文档为准