
sidebar.wechat

sidebar.feishu
sidebar.chooseYourWayToJoin

sidebar.scanToAddConsultant
In enterprise-level data analysis scenarios, data security is paramount. Users of different roles should only access data within their permission scope. AskTable provides a complete permission control system supporting four-level permission control at database/table/field/row levels.
This article provides a comprehensive explanation of AskTable's permission control mechanism to help you build a secure and reliable data analysis system.
Scenario 1: Multi-Tenant Data Isolation
Scenario 2: Subsidiary Data Permissions
Scenario 3: Sensitive Field Protection
Scenario 4: Environment Isolation
Application Layer Control:
Database Views:
AskTable's Solution:
AskTable supports permission control at each level:
An Access Policy defines what data a person can (or cannot) access.
Core Attributes:
permission: Access permission (allow or deny)name: Policy namedataset_config: Dataset configurationPolicy Types:
A Role is a collection of access policies. Users access data by assuming roles.
Role Characteristics:
{{user_id}})Control which datasources can be accessed:
{
"permission": "allow",
"name": "production_only",
"dataset_config": {
"datasource_ids": "ds_prod_001"
}
}
Effect:
Using Regular Expression Matching:
{
"permission": "allow",
"name": "public_tables_only",
"dataset_config": {
"datasource_ids": "*",
"regex_patterns": {
"schemas_regex_pattern": "^public$",
"tables_regex_pattern": "^(users|orders|products)$"
}
}
}
Effect:
Hiding Sensitive Fields:
{
"permission": "deny",
"name": "hide_sensitive_fields",
"dataset_config": {
"datasource_ids": "*",
"regex_patterns": {
"fields_regex_pattern": ".*password.*|.*pwd.*|.*phone.*|.*id_card.*"
}
}
}
Effect:
Filtering Data Rows:
{
"permission": "allow",
"name": "regional_data",
"dataset_config": {
"datasource_ids": "ds_001",
"rows_filters": {
"ds_001": [
"public.orders.region = {{region}}",
"public.users.status = 'active'"
]
}
}
}
Effect:
Dynamic variables allow passing parameters at query time to achieve more flexible permission control.
Syntax: {{variable_name}}
Supported Variable Types:
{{user_id}}{{region}}{{department_id}}Defining Policy:
{
"permission": "allow",
"name": "user_own_data",
"dataset_config": {
"datasource_ids": "ds_001",
"rows_filters": {
"ds_001": [
"public.orders.user_id = {{user_id}}",
"public.*.created_by = {{user_id}}"
]
}
}
}
Passing Variables at Query Time:
from asktable import Asktable
client = Asktable(api_key="your_api_key")
# Pass user_id when querying
response = client.answers.create(
datasource_id="ds_001",
question="Query my orders",
role_id="role_employee",
role_variables={"user_id": "12345"}
)
Actually Executed SQL:
SELECT * FROM orders
WHERE user_id = '12345' -- Automatically injected
Supported Operators:
=!=, <>>, <, >=, <=IN (value1, value2)LIKE 'pattern'IS NULL, IS NOT NULLSupported Functions:
NOW(): Current timeNOW() - 1 YEAR, NOW() - 30 DAYExample:
{
"rows_filters": {
"ds_001": [
"public.orders.created_at > NOW() - 30 DAY",
"public.orders.amount >= 1000",
"public.orders.status IN ('paid', 'shipped')"
]
}
}
Scenario: SaaS platform, each tenant can only see their own data
Step 1: Create Access Policy
{
"permission": "allow",
"name": "tenant_isolation",
"dataset_config": {
"datasource_ids": "ds_saas",
"rows_filters": {
"ds_saas": [
"*.*.tenant_id = {{tenant_id}}"
]
}
}
}
Step 2: Create Role
{
"name": "tenant_user",
"policies": ["tenant_isolation"]
}
Step 3: Pass Tenant ID at Query Time
response = client.answers.create(
datasource_id="ds_saas",
question="Query total users",
role_id="role_tenant_user",
role_variables={"tenant_id": "tenant_abc"}
)
Effect:
Scenario: Group company, subsidiaries can only see their own regional data
Step 1: Create Regional Policy
{
"permission": "allow",
"name": "regional_access",
"dataset_config": {
"datasource_ids": "ds_erp",
"rows_filters": {
"ds_erp": [
"public.orders.region = {{region}}",
"public.customers.region = {{region}}",
"public.employees.region = {{region}}"
]
}
}
}
Step 2: Create Role
{
"name": "regional_manager",
"policies": ["regional_access"]
}
Step 3: Queries from Different Regions
# Shanghai subsidiary
response = client.answers.create(
datasource_id="ds_erp",
question="Query this month's sales",
role_id="role_regional_manager",
role_variables={"region": "Shanghai"}
)
# Beijing subsidiary
response = client.answers.create(
datasource_id="ds_erp",
question="Query this month's sales",
role_id="role_regional_manager",
role_variables={"region": "Beijing"}
)
Scenario: Regular employees cannot view sensitive information like phone numbers and ID cards
Step 1: Create Sensitive Field Deny Policy
{
"permission": "deny",
"name": "hide_pii",
"dataset_config": {
"datasource_ids": "*",
"regex_patterns": {
"fields_regex_pattern": ".*phone.*|.*mobile.*|.*id_card.*|.*ssn.*|.*credit_card.*"
}
}
}
Step 2: Create Regular Employee Role
{
"name": "employee",
"policies": ["hide_pii"]
}
Step 3: Create Administrator Role (Unrestricted)
{
"name": "admin",
"policies": [] // Unrestricted
}
Effect:
Scenario: Employees can only query data from the last 90 days
Step 1: Create Time Restriction Policy
{
"permission": "allow",
"name": "recent_data_only",
"dataset_config": {
"datasource_ids": "ds_001",
"rows_filters": {
"ds_001": [
"*.*.created_at > NOW() - 90 DAY"
]
}
}
}
Effect:
Only grant necessary permissions:
Example:
// Bad practice: grant all permissions
{
"permission": "allow",
"dataset_config": {
"datasource_ids": "*"
}
}
// Good practice: explicitly specify
{
"permission": "allow",
"dataset_config": {
"datasource_ids": "ds_001",
"regex_patterns": {
"tables_regex_pattern": "^(users|orders)$"
}
}
}
Recommended permission hierarchy:
Flexible matching of table and field names:
{
"regex_patterns": {
// Match all tables starting with user_
"tables_regex_pattern": "^user_.*$",
// Match all tables containing temp or test
"tables_regex_pattern": ".*(temp|test).*",
// Match all sensitive fields
"fields_regex_pattern": ".*(password|pwd|secret|token|key).*"
}
}
Recommended naming conventions:
Example:
✅ user_id
✅ department_id
✅ region_code
✅ start_date
❌ uid
❌ did
❌ r
❌ sd
Testing Checklist:
Method 1: Use MCP Testing
from asktable import Asktable
client = Asktable(api_key="your_api_key")
# Test query
response = client.sqls.create(
datasource_id="ds_001",
question="Query all users",
role_id="role_employee",
role_variables={"user_id": "12345"}
)
# View generated SQL
print(response.query.sql)
# Should include: WHERE user_id = '12345'
Method 2: View SQL Directly
In AskTable interface:
Problem 1: Permissions Not Taking Effect
Check:
Problem 2: Dynamic Variables Not Replaced
Check:
Problem 3: Permissions Too Strict
Check:
A role can contain multiple policies:
{
"name": "sales_manager",
"policies": [
"regional_access", // Regional restriction
"hide_pii", // Hide sensitive information
"recent_data_only" // Time restriction
]
}
Policy Priority:
Datasource Wildcard:
{
"datasource_ids": "*" // All datasources
}
Table Name Wildcard:
{
"rows_filters": {
"ds_001": [
"*.*.user_id = {{user_id}}" // user_id field across all tables
]
}
}
Multiple Condition Combinations:
{
"rows_filters": {
"ds_001": [
"public.orders.user_id = {{user_id}}",
"public.orders.status IN ('paid', 'shipped')",
"public.orders.created_at > NOW() - 30 DAY"
]
}
}
Note:
AskTable's permission control system provides:
Core Capabilities: ✅ Four-level permission control (datasource/Schema/table/field/row) ✅ Dynamic permission variables ✅ Flexible policy combinations ✅ Automatic SQL rewriting
Best Practices: ✅ Follow the principle of least privilege ✅ Use dynamic variables for flexible control ✅ Regularly review and test permission configuration ✅ Document permission design
Next Steps:
Related Reading:
Technical Exchange:
sidebar.noProgrammingNeeded
sidebar.startFreeTrial