Skip to content

Commit a6e7bc8

Browse files
authored
Merge pull request #11 from aspicas/develop
Develop
2 parents 3972a2f + 7c57e25 commit a6e7bc8

21 files changed

+1498
-228
lines changed

example/lib/demo_content.dart

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
import 'dart:developer';
2+
3+
import 'package:flutter/material.dart';
4+
import 'package:flutter_policy_engine/flutter_policy_engine.dart';
5+
6+
class DemoContent extends StatefulWidget {
7+
const DemoContent({super.key});
8+
9+
@override
10+
State<DemoContent> createState() => _DemoContentState();
11+
}
12+
13+
class _DemoContentState extends State<DemoContent> {
14+
String _currentRole = 'guest';
15+
16+
@override
17+
Widget build(BuildContext context) {
18+
return Padding(
19+
padding: const EdgeInsets.all(16.0),
20+
child: Column(
21+
crossAxisAlignment: CrossAxisAlignment.start,
22+
children: [
23+
Text(
24+
'Rol actual: $_currentRole',
25+
style: Theme.of(context).textTheme.headlineSmall,
26+
),
27+
const SizedBox(height: 16),
28+
29+
// Selector de rol
30+
Row(
31+
children: [
32+
_buildRoleButton('guest'),
33+
const SizedBox(width: 8),
34+
_buildRoleButton('user'),
35+
const SizedBox(width: 8),
36+
_buildRoleButton('admin'),
37+
],
38+
),
39+
40+
const SizedBox(height: 32),
41+
42+
// Ejemplos de PolicyWidget
43+
_buildPolicyExample('LoginPage', 'Página de Login'),
44+
_buildPolicyExample('Dashboard', 'Dashboard'),
45+
_buildPolicyExample('UserManagement', 'Gestión de Usuarios'),
46+
_buildPolicyExample('Settings', 'Configuración'),
47+
48+
const SizedBox(height: 32),
49+
],
50+
),
51+
);
52+
}
53+
54+
Widget _buildRoleButton(String role) {
55+
return ElevatedButton(
56+
onPressed: () {
57+
setState(() {
58+
_currentRole = role;
59+
});
60+
},
61+
style: ElevatedButton.styleFrom(
62+
backgroundColor: _currentRole == role ? Colors.blue : Colors.grey,
63+
),
64+
child: Text(role),
65+
);
66+
}
67+
68+
Widget _buildPolicyExample(String content, String displayName) {
69+
return Padding(
70+
padding: const EdgeInsets.only(bottom: 16),
71+
child: Column(
72+
crossAxisAlignment: CrossAxisAlignment.start,
73+
children: [
74+
Text('$displayName:'),
75+
const SizedBox(height: 4),
76+
PolicyWidget(
77+
role: _currentRole,
78+
content: content,
79+
fallback: Card(
80+
color: Colors.red[100],
81+
child: Padding(
82+
padding: const EdgeInsets.all(16),
83+
child: Text('Acceso denegado para $displayName'),
84+
),
85+
),
86+
onAccessDenied: () {
87+
log('Acceso denegado para $_currentRole a $content');
88+
},
89+
child: Card(
90+
color: Colors.green[100],
91+
child: Padding(
92+
padding: const EdgeInsets.all(16),
93+
child: Text('Acceso permitido a $displayName'),
94+
),
95+
),
96+
),
97+
],
98+
),
99+
);
100+
}
101+
}

example/lib/main.dart

Lines changed: 1 addition & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
1-
import 'dart:developer';
2-
31
import 'package:flutter/material.dart';
4-
import 'package:flutter_policy_engine/flutter_policy_engine.dart';
2+
import 'package:flutter_policy_engine_example/policy_engine_demo.dart';
53

64
void main() {
75
runApp(const MyApp());
@@ -22,67 +20,3 @@ class MyApp extends StatelessWidget {
2220
);
2321
}
2422
}
25-
26-
class PolicyEngineDemo extends StatefulWidget {
27-
const PolicyEngineDemo({super.key});
28-
29-
@override
30-
State<StatefulWidget> createState() {
31-
return _PolicyEngineDemoState();
32-
}
33-
}
34-
35-
class _PolicyEngineDemoState extends State<PolicyEngineDemo> {
36-
late PolicyManager policyManager;
37-
bool _isInitialized = false;
38-
39-
@override
40-
void initState() {
41-
super.initState();
42-
_initializePolicyManager();
43-
}
44-
45-
Future<void> _initializePolicyManager() async {
46-
policyManager = PolicyManager();
47-
final policies = {
48-
"admin": ["LoginPage", "Dashboard", "UserManagement", "Settings"],
49-
"user": ["LoginPage", "Dashboard"],
50-
"guest": ["LoginPage"]
51-
};
52-
try {
53-
await policyManager.initialize(policies);
54-
setState(() {
55-
_isInitialized = true;
56-
});
57-
} catch (e) {
58-
log(e.toString());
59-
setState(() {
60-
_isInitialized = false;
61-
});
62-
}
63-
}
64-
65-
@override
66-
Widget build(BuildContext context) {
67-
if (!_isInitialized) {
68-
return Scaffold(
69-
appBar: AppBar(
70-
title: const Text('Policy Engine Demo'),
71-
),
72-
body: const Center(
73-
child: Column(
74-
mainAxisAlignment: MainAxisAlignment.center,
75-
children: [
76-
CircularProgressIndicator(),
77-
SizedBox(height: 16),
78-
Text('Loading policies...'),
79-
],
80-
),
81-
),
82-
);
83-
}
84-
return const Center(
85-
child: Text('Policies loaded'),
86-
);
87-
}
88-
}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import 'dart:developer';
2+
3+
import 'package:flutter/material.dart';
4+
import 'package:flutter_policy_engine/flutter_policy_engine.dart';
5+
import 'package:flutter_policy_engine_example/demo_content.dart';
6+
7+
class PolicyEngineDemo extends StatefulWidget {
8+
const PolicyEngineDemo({super.key});
9+
10+
@override
11+
State<StatefulWidget> createState() {
12+
return _PolicyEngineDemoState();
13+
}
14+
}
15+
16+
class _PolicyEngineDemoState extends State<PolicyEngineDemo> {
17+
late PolicyManager policyManager;
18+
bool _isInitialized = false;
19+
20+
@override
21+
void initState() {
22+
super.initState();
23+
_initializePolicyManager();
24+
}
25+
26+
Future<void> _initializePolicyManager() async {
27+
policyManager = PolicyManager();
28+
final policies = {
29+
"admin": ["LoginPage", "Dashboard", "UserManagement", "Settings"],
30+
"user": ["LoginPage", "Dashboard"],
31+
"guest": ["LoginPage"]
32+
};
33+
try {
34+
await policyManager.initialize(policies);
35+
setState(() {
36+
_isInitialized = true;
37+
});
38+
} catch (e) {
39+
log(e.toString());
40+
setState(() {
41+
_isInitialized = false;
42+
});
43+
}
44+
}
45+
46+
@override
47+
Widget build(BuildContext context) {
48+
if (!_isInitialized) {
49+
return Scaffold(
50+
appBar: AppBar(
51+
title: const Text('Policy Engine Demo'),
52+
),
53+
body: const Center(
54+
child: Column(
55+
mainAxisAlignment: MainAxisAlignment.center,
56+
children: [
57+
CircularProgressIndicator(),
58+
SizedBox(height: 16),
59+
Text('Loading policies...'),
60+
],
61+
),
62+
),
63+
);
64+
}
65+
return PolicyProvider(
66+
policyManager: policyManager,
67+
child: Scaffold(
68+
appBar: AppBar(
69+
title: const Text('Policy Engine Demo'),
70+
),
71+
body: const DemoContent(),
72+
),
73+
);
74+
}
75+
}

lib/flutter_policy_engine.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
library flutter_policy_engine;
22

33
export 'src/core/policy_manager.dart';
4+
export 'src/widgets/policy_widget.dart';
5+
export 'src/core/policy_provider.dart';

lib/src/core/policy_manager.dart

Lines changed: 53 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -86,54 +86,43 @@ class PolicyManager extends ChangeNotifier {
8686
final key = entry.key;
8787
final value = entry.value;
8888

89-
try {
90-
if (value == null) {
91-
LogHandler.warning(
92-
'Skipping null policy value',
93-
context: {'role': key},
94-
operation: 'policy_validation_skip',
95-
);
96-
continue;
97-
}
98-
99-
if (value is! List) {
100-
LogHandler.warning(
101-
'Skipping invalid policy value type',
102-
context: {
103-
'role': key,
104-
'expected_type': 'List',
105-
'actual_type': value.runtimeType.toString(),
106-
},
107-
operation: 'policy_validation_skip',
108-
);
109-
continue;
110-
}
111-
112-
if (value.any((item) => item is! String)) {
113-
LogHandler.warning(
114-
'Skipping policy with non-string content items',
115-
context: {'role': key},
116-
operation: 'policy_validation_skip',
117-
);
118-
continue;
119-
}
120-
121-
// Create the policy and add to valid policies
122-
final policy = Policy(
123-
roleName: key,
124-
allowedContent: value.cast<String>(),
89+
if (value == null) {
90+
LogHandler.warning(
91+
'Skipping null policy value',
92+
context: {'role': key},
93+
operation: 'policy_validation_skip',
94+
);
95+
continue;
96+
}
97+
98+
if (value is! List) {
99+
LogHandler.warning(
100+
'Skipping invalid policy value type',
101+
context: {
102+
'role': key,
103+
'expected_type': 'List',
104+
'actual_type': value.runtimeType.toString(),
105+
},
106+
operation: 'policy_validation_skip',
125107
);
126-
validPolicies[key] = policy.toJson();
127-
} catch (e, stackTrace) {
128-
LogHandler.error(
129-
'Failed to process policy',
130-
error: e,
131-
stackTrace: stackTrace,
108+
continue;
109+
}
110+
111+
if (value.any((item) => item is! String)) {
112+
LogHandler.warning(
113+
'Skipping policy with non-string content items',
132114
context: {'role': key},
133-
operation: 'policy_processing_error',
115+
operation: 'policy_validation_skip',
134116
);
135-
// Continue with other policies
117+
continue;
136118
}
119+
120+
// Create the policy and add to valid policies
121+
final policy = Policy(
122+
roleName: key,
123+
allowedContent: value.cast<String>(),
124+
);
125+
validPolicies[key] = policy.toJson();
137126
}
138127

139128
_policies = JsonHandler.parseMap(
@@ -185,4 +174,24 @@ class PolicyManager extends ChangeNotifier {
185174
rethrow;
186175
}
187176
}
177+
178+
/// Checks if the specified [role] has access to the given [content].
179+
///
180+
/// Returns `true` if the policy manager is initialized and the evaluator
181+
/// determines that the [role] is permitted to access the [content].
182+
/// Returns `false` if the policy manager is not initialized, the evaluator
183+
/// is not set, or if access is denied.
184+
///
185+
/// Logs an error if called before initialization or if the evaluator is missing.
186+
bool hasAccess(String role, String content) {
187+
if (!_isInitialized || _evaluator == null) {
188+
LogHandler.error(
189+
'Policy manager not initialized or evaluator not set',
190+
context: {'role': role, 'content': content},
191+
operation: 'policy_manager_access_check',
192+
);
193+
return false;
194+
}
195+
return _evaluator!.evaluate(role, content);
196+
}
188197
}

0 commit comments

Comments
 (0)