JSON Assets Demo
Loading policies from external JSON asset files
JSON Assets Demo
This example demonstrates how to load and manage policies from external JSON asset files using the initializeFromJsonAssets
method. This approach is ideal for applications that need to bundle policy configurations with the app or load them from external sources.
šÆ Demo Overview
The JSON Assets Demo showcases:
- External Policy Loading: Loading policies from JSON files bundled as assets
- Dynamic Role Management: Interactive role selection and permission testing
- Real-time Validation: Testing permissions against loaded policies
- Error Handling: Graceful handling of initialization failures
- Visual Feedback: Clear status indicators and result displays
š Asset File Structure
The demo uses a JSON asset file located at assets/policies/user_roles.json
with the following structure:
{
"admin": {
"allowedContent": [
"read",
"write",
"delete",
"manage_users",
"system_config",
"all",
"admin_panel",
"user_management",
"system_settings"
]
},
"manager": {
"allowedContent": [
"read",
"write",
"manage_team",
"team_content",
"reports",
"analytics",
"public"
]
},
"editor": {
"allowedContent": [
"read",
"write",
"publish",
"content_creation",
"drafts",
"published_content",
"public"
]
},
"viewer": {
"allowedContent": ["read", "public", "published_content", "reports"]
},
"guest": {
"allowedContent": ["read", "public"]
}
}
š Complete Demo Implementation
import 'package:flutter/material.dart';
import 'package:flutter_policy_engine/flutter_policy_engine.dart';
class JsonAssetsDemo extends StatefulWidget {
const JsonAssetsDemo({super.key});
@override
State<JsonAssetsDemo> createState() => _JsonAssetsDemoState();
}
class _JsonAssetsDemoState extends State<JsonAssetsDemo> {
final PolicyManager _policyManager = PolicyManager();
bool _isInitialized = false;
bool _isLoading = false;
String _selectedRole = 'admin';
String _selectedPermission = 'read';
String _lastResult = '';
String _errorMessage = '';
final List<String> _availableRoles = [
'admin',
'manager',
'editor',
'viewer',
'guest',
];
final List<String> _availablePermissions = [
'read',
'write',
'delete',
'manage_users',
'system_config',
'manage_team',
'publish',
];
@override
void initState() {
super.initState();
_initializePolicyManager();
}
Future<void> _initializePolicyManager() async {
setState(() {
_isLoading = true;
_errorMessage = '';
});
try {
await _policyManager
.initializeFromJsonAssets('assets/policies/user_roles.json');
setState(() {
_isInitialized = _policyManager.isInitialized;
_isLoading = false;
_lastResult = _isInitialized
? 'ā
Policy manager initialized successfully from JSON assets!'
: 'ā Failed to initialize policy manager';
});
} catch (e) {
setState(() {
_isLoading = false;
_errorMessage = 'Error: $e';
_lastResult = 'ā Initialization failed';
});
}
}
void _testPermission() {
if (!_isInitialized) {
setState(() {
_lastResult = 'ā Policy manager not initialized';
});
return;
}
try {
final role = _policyManager.roles[_selectedRole];
if (role != null) {
final hasPermission = role.allowedContent.contains(_selectedPermission);
setState(() {
_lastResult = hasPermission
? 'ā
Role "$_selectedRole" has permission "$_selectedPermission"'
: 'ā Role "$_selectedRole" does NOT have permission "$_selectedPermission"';
});
} else {
setState(() {
_lastResult = 'ā Role "$_selectedRole" not found';
});
}
} catch (e) {
setState(() {
_lastResult = 'ā Error testing permission: $e';
});
}
}
void _getRoleInfo() {
if (!_isInitialized) {
setState(() {
_lastResult = 'ā Policy manager not initialized';
});
return;
}
try {
final role = _policyManager.roles[_selectedRole];
if (role != null) {
setState(() {
_lastResult = '''
ā
Role Information for "$_selectedRole":
Name: ${role.name}
Allowed Content: ${role.allowedContent.join(', ')}
''';
});
} else {
setState(() {
_lastResult = 'ā Role "$_selectedRole" not found';
});
}
} catch (e) {
setState(() {
_lastResult = 'ā Error getting role info: $e';
});
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('JSON Assets Demo'),
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
),
body: SingleChildScrollView(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
// Initialization Status Card
Card(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Icon(
_isInitialized ? Icons.check_circle : Icons.error,
color: _isInitialized ? Colors.green : Colors.red,
),
const SizedBox(width: 8),
Text(
'Policy Manager Status',
style: Theme.of(context).textTheme.titleMedium,
),
],
),
const SizedBox(height: 8),
if (_isLoading)
const LinearProgressIndicator()
else
Text(
_isInitialized
? 'ā
Initialized from JSON assets'
: 'ā Not initialized',
style: Theme.of(context).textTheme.bodyMedium,
),
if (_errorMessage.isNotEmpty) ...[
const SizedBox(height: 8),
Text(
_errorMessage,
style: Theme.of(context).textTheme.bodySmall?.copyWith(
color: Colors.red,
),
),
],
const SizedBox(height: 16),
ElevatedButton.icon(
onPressed: _isLoading ? null : _initializePolicyManager,
icon: const Icon(Icons.refresh),
label: const Text('Reinitialize'),
),
],
),
),
),
const SizedBox(height: 16),
// Role Selection Card
Card(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Role Selection',
style: Theme.of(context).textTheme.titleMedium,
),
const SizedBox(height: 16),
DropdownButtonFormField<String>(
value: _selectedRole,
decoration: const InputDecoration(
labelText: 'Select Role',
border: OutlineInputBorder(),
),
items: _availableRoles.map((role) {
return DropdownMenuItem(
value: role,
child: Text(role),
);
}).toList(),
onChanged: (value) {
if (value != null) {
setState(() {
_selectedRole = value;
});
}
},
),
],
),
),
),
const SizedBox(height: 16),
// Permission Testing Card
Card(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Permission Testing',
style: Theme.of(context).textTheme.titleMedium,
),
const SizedBox(height: 16),
DropdownButtonFormField<String>(
value: _selectedPermission,
decoration: const InputDecoration(
labelText: 'Select Permission',
border: OutlineInputBorder(),
),
items: _availablePermissions.map((permission) {
return DropdownMenuItem(
value: permission,
child: Text(permission),
);
}).toList(),
onChanged: (value) {
if (value != null) {
setState(() {
_selectedPermission = value;
});
}
},
),
const SizedBox(height: 16),
ElevatedButton.icon(
onPressed: _isInitialized ? _testPermission : null,
icon: const Icon(Icons.security),
label: const Text('Test Permission'),
style: ElevatedButton.styleFrom(
backgroundColor: Colors.blue,
foregroundColor: Colors.white,
),
),
],
),
),
),
const SizedBox(height: 16),
// Role Information Card
Card(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Role Information',
style: Theme.of(context).textTheme.titleMedium,
),
const SizedBox(height: 16),
ElevatedButton.icon(
onPressed: _isInitialized ? _getRoleInfo : null,
icon: const Icon(Icons.info),
label: const Text('Get Role Details'),
style: ElevatedButton.styleFrom(
backgroundColor: Colors.orange,
foregroundColor: Colors.white,
),
),
],
),
),
),
const SizedBox(height: 16),
// Results Card
if (_lastResult.isNotEmpty)
Card(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Test Results',
style: Theme.of(context).textTheme.titleMedium,
),
const SizedBox(height: 16),
Container(
width: double.infinity,
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: Colors.grey[100],
borderRadius: BorderRadius.circular(8),
border: Border.all(color: Colors.grey[300]!),
),
child: Text(
_lastResult,
style:
Theme.of(context).textTheme.bodyMedium?.copyWith(
fontFamily: 'monospace',
),
),
),
],
),
),
),
],
),
),
);
}
}
1. Asset Declaration
Add the JSON asset file to your pubspec.yaml
:
flutter:
assets:
- assets/policies/user_roles.json
2. File Structure
Ensure your project has the following structure:
your_app/
āāā assets/
ā āāā policies/
ā āāā user_roles.json
āāā lib/
ā āāā json_assets_demo.dart
āāā pubspec.yaml
Initialization Process
The demo initializes the policy manager using initializeFromJsonAssets
:
await _policyManager.initializeFromJsonAssets('assets/policies/user_roles.json');
This method:
- Loads the JSON file from assets
- Parses the JSON structure
- Creates
Role
objects from the parsed data - Initializes the policy manager with the loaded policies
Error Handling
The implementation includes comprehensive error handling:
try {
await _policyManager.initializeFromJsonAssets('assets/policies/user_roles.json');
setState(() {
_isInitialized = _policyManager.isInitialized;
_isLoading = false;
_lastResult = _isInitialized
? 'ā
Policy manager initialized successfully from JSON assets!'
: 'ā Failed to initialize policy manager';
});
} catch (e) {
setState(() {
_isLoading = false;
_errorMessage = 'Error: $e';
_lastResult = 'ā Initialization failed';
});
}
Permission Testing
The demo provides real-time permission testing:
void _testPermission() {
if (!_isInitialized) return;
final role = _policyManager.roles[_selectedRole];
if (role != null) {
final hasPermission = role.allowedContent.contains(_selectedPermission);
// Update UI with result
}
}
šÆ Use Cases
This approach is ideal for:
- Configuration Management: Centralizing policy configurations in external files
- Dynamic Updates: Updating policies without code changes
- Environment-Specific Policies: Different policies for development, staging, and production
- Localization: Different policies for different regions or user groups
- A/B Testing: Testing different policy configurations
1. Asset Validation
Always validate your JSON structure before deployment:
// Validate JSON structure
try {
final testManager = PolicyManager();
await testManager.initializeFromJsonAssets('assets/policies/user_roles.json');
print('ā
JSON structure is valid');
} catch (e) {
print('ā JSON structure error: $e');
}
2. Error Recovery
Implement fallback mechanisms:
Future<void> initializeWithFallback() async {
try {
await _policyManager.initializeFromJsonAssets('assets/policies/user_roles.json');
} catch (e) {
// Fallback to default policies
await _policyManager.initialize(defaultPolicies);
}
}
š Next Steps
- Explore Role Management Demo for advanced role operations
- Learn about Policy Management concepts
- Check out the Quick Start guide for basic setup