Skip to content

feat: add JSON string support for ABAC enforcement#59

Merged
nomeguy merged 7 commits intomasterfrom
copilot/implement-abac-with-casbin
Dec 7, 2025
Merged

feat: add JSON string support for ABAC enforcement#59
nomeguy merged 7 commits intomasterfrom
copilot/implement-abac-with-casbin

Conversation

Copy link
Contributor

Copilot AI commented Nov 17, 2025

Minimized code changes to only include the core JSON string support functionality in CasbinEvaluator.

Changes

  • Enhanced CasbinEvaluator.evalMemberExpression() to handle JSON strings, Maps, and AbacClass objects
  • Parses JSON strings via jsonDecode() before property access
  • Falls back to .toMap() for backward compatibility
  • Provides clear error messages for unsupported types
  • Applied Dart formatting to pass CI checks

Files Changed

  • lib/src/utils/utils.dart - Added JSON string parsing support with proper formatting

All 452 existing tests pass. Backward compatible with existing AbacClass implementations.

Original prompt

This section details on the original issue you should resolve

<issue_title>Implementing ABAC with Casbin in Flutter</issue_title>
<issue_description>## Issue with Casbin ABAC in Flutter – Need Help!

I'm trying to implement Attribute-Based Access Control (ABAC) using Casbin in my Flutter application. While the setup works fine for Role-Based Access Control (RBAC), ABAC enforcement isn't working as expected.

I've set up a Casbin model with a policy that should allow access if the user's age is between 18 and 60. However, the enforcement always returns false, denying access even when the conditions should be met.

Here’s my setup:

Casbin Model:

[request_definition]
r = sub, obj, act

[policy_definition]
p = sub, obj, act, condition

[policy_effect]
e = some(where (p.eft == allow))

[matchers]
m = eval(p.condition) && r.obj == p.obj && r.act == p.act

Casbin Policy:

p, {"age": 18}, /data1, read, r.sub.age >= 18 && r.sub.age < 60

Flutter Code:

import 'package:flutter/material.dart';
import 'package:casbin/casbin.dart';
import 'dart:convert';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Casbin ABAC Demo',
      theme: ThemeData(primarySwatch: Colors.blue),
      home: ABACScreen(),
    );
  }
}

class ABACScreen extends StatefulWidget {
  @override
  _ABACScreenState createState() => _ABACScreenState();
}

class _ABACScreenState extends State<ABACScreen> {
  final TextEditingController ageController = TextEditingController();
  String resultMessage = "";

  Future<void> checkAccess() async {
    int? age = int.tryParse(ageController.text);
    if (age == null) {
      setState(() {
        resultMessage = "❌ Please enter a valid age.";
      });
      return;
    }

    final model = Model()..loadModelFromText(getModel());
    final enforcer = await Enforcer.fromModelAndAdapter(model);

    // Load policies
    getPolicy().split('\n').forEach((element) {
      if (element.trim().isNotEmpty) {
        final parts = element.split(',').map((e) => e.trim()).toList();
        if (parts.length == 5) {
          enforcer.addPolicy([parts[0], parts[1], parts[2], parts[3], parts[4]]);
        }
      }
    });

    try {
      String subJson = jsonEncode({"age": age});
      bool? result = await enforcer.enforce([subJson, '/data1', 'read']);

      setState(() {
        resultMessage = result??false ? "✅ Access Granted" : "❌ Access Denied";
      });
    } catch (e) {
      debugPrint("⚠️ Error: $e");
      setState(() {
        resultMessage = "⚠️ Error: ${e.toString()}";
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text("Casbin ABAC Demo")),
      body: Padding(
        padding: EdgeInsets.all(20),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            TextField(
              controller: ageController,
              keyboardType: TextInputType.number,
              decoration: InputDecoration(labelText: "Age", border: OutlineInputBorder()),
            ),
            SizedBox(height: 20),
            ElevatedButton(
              onPressed: checkAccess,
              child: Text("Check Access"),
            ),
            SizedBox(height: 20),
            SelectableText(resultMessage, style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
          ],
        ),
      ),
    );
  }
}

// Casbin Model
String getModel() {
  return '''
[request_definition]
r = sub, obj, act

[policy_definition]
p = sub, obj, act, condition

[policy_effect]
e = some(where (p.eft == allow))

[matchers]
m = eval(p.condition) && r.obj == p.obj && r.act == p.act
''';
}

// Casbin Policy
String getPolicy() {
  return '''
p, {"age": 18}, /data1, read, r.sub.age >= 18 && r.sub.age < 60
''';
}

Issue:

Even when I enter an age within the valid range (e.g., 25), Casbin denies access. It seems like the ABAC condition r.sub.age >= 18 && r.sub.age < 60 isn't being evaluated correctly.

Has anyone successfully implemented ABAC with Casbin in Flutter? What am I missing? Any help would be appreciated! 🚀</issue_description>

Comments on the Issue (you are @copilot in this section)

@hsluoyz @ankit3r try Casbin editor first: https://editor.casbin.org/

💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

@CLAassistant
Copy link

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

@nomeguy nomeguy marked this pull request as ready for review November 17, 2025 13:36
Copilot AI and others added 4 commits November 17, 2025 13:38
Co-authored-by: nomeguy <85475922+nomeguy@users.noreply.github.com>
Co-authored-by: nomeguy <85475922+nomeguy@users.noreply.github.com>
Co-authored-by: nomeguy <85475922+nomeguy@users.noreply.github.com>
Co-authored-by: nomeguy <85475922+nomeguy@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix ABAC enforcement with Casbin in Flutter Add JSON string support for ABAC enforcement Nov 17, 2025
Copilot AI requested a review from nomeguy November 17, 2025 13:48
@nomeguy
Copy link

nomeguy commented Dec 6, 2025

@copilot don't add README, don't add any new test code, keep the code diff minimized

…lity

Co-authored-by: nomeguy <85475922+nomeguy@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Dec 6, 2025

@copilot don't add README, don't add any new test code, keep the code diff minimized

Done. Removed README changes, all test files, and examples. Only kept the core functionality change in lib/src/utils/utils.dart (+32 lines, -1 line). All 452 existing tests still pass. (commit 305682b)

@nomeguy
Copy link

nomeguy commented Dec 6, 2025

@copilot fix failed CI check:

Run dart format --output=none --set-exit-if-changed .
  dart format --output=none --set-exit-if-changed .
  shell: /usr/bin/bash -e {0}
  env:
    PUB_ENVIRONMENT: bot.github
    DART_HOME: /opt/hostedtoolcache/dart/3.10.3/x64
    PUB_CACHE: /home/runner/.pub-cache
Changed lib/src/utils/utils.dart
Formatted 50 files (1 changed) in 0.07 seconds.
Error: Process completed with exit code 1.

Co-authored-by: nomeguy <85475922+nomeguy@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Dec 6, 2025

@copilot fix failed CI check:

...

Fixed. Applied dart format to the file. CI check should now pass. (commit 0ca4322)

@nomeguy nomeguy changed the title Add JSON string support for ABAC enforcement feat: add JSON string support for ABAC enforcement Dec 7, 2025
@nomeguy nomeguy merged commit 974b83a into master Dec 7, 2025
7 of 8 checks passed
github-actions bot pushed a commit that referenced this pull request Dec 7, 2025
# [1.8.0](v1.7.0...v1.8.0) (2025-12-07)

### Features

* add JSON string support for ABAC enforcement ([#59](#59)) ([b4eb1f9](b4eb1f9))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Implementing ABAC with Casbin in Flutter

3 participants