Skip to main content

guardify 1.2.0 copy "guardify: ^1.2.0" to clipboard
guardify: ^1.2.0 copied to clipboard

A Dart code generation package for Role-Based UI Access Control in Flutter widgets.

Guardify πŸ›‘οΈ #

A powerful, type-safe Role-Based UI Access Control (RBAC) and Permission-Based Access Control (PBAC) framework for Flutter apps, offering both Annotation-Based Code Generation and Zero-Boilerplate Runtime Widgets.

pub package License: MIT Flutter


πŸ”’ Security Best Practices & Architectural Notice #

Important

Client-Side UI Gating vs. Server-Side Enforcement (Defense in Depth)

Guardify is designed for the Presentation Layer (UI/UX):

  • It prevents unauthorized UI components from rendering or executing client-side callbacks (onPressed, onTap).
  • It delivers smooth, clean UX by hiding restricted buttons, displaying disabled states with lock badges, and handling route redirects before screens mount.

However, client-side code runs on user-controlled hardware and can theoretically be inspected or manipulated:

  • Never rely exclusively on client-side UI gating for data security.
  • Server-Side Enforcement is Mandatory: Sensitive data operations, database queries, and mutation endpoints (e.g. DELETE / POST API calls) must always be authenticated and authorized on the backend server or cloud security layer (e.g., Firebase Security Rules, Supabase Row-Level Security (RLS), Node.js / Go / Spring Boot JWT claim validators).
  • Verified Claims: Always supply currentRole, currentRoles, or currentPermissions to GuardifyScope from cryptographically verified authentication sources (such as verified JWT token claims, Firebase Auth Custom Claims, or Auth0 access tokens).
  • Secure by Default: Guardify follows the principle of least privilegeβ€”if roles or permissions do not match, or if GuardifyScope is missing from the tree, access is safely denied by default.

✨ Features #

  • πŸ›‘οΈ Dual-Mode Access Control:
    • Runtime Widget (RoleGate / SecuredFeature): Protect any Flutter or 3rd-party widget on-the-fly with Zero build_runner required.
    • Code Generation (@Secured): Type-safe, component-level security policies declared on widget classes.
  • ⚑ Zero Prop-Drilling: Ambient role & permission state resolution via GuardifyScope (InheritedWidget).
  • πŸ”„ Reactive State Binding: Connect directly to ValueListenable, ChangeNotifier, or Stream using GuardifyScope.listenable or GuardifyScope.stream for automatic rebuilds on auth changes.
  • 🎨 Flexible Fallback UI Strategies:
    • FallbackType.hide (default): Silently hides unauthorized widgets (const SizedBox.shrink()).
    • FallbackType.disabled: Disables user interactions (AbsorbPointer) with reduced opacity and optional lock overlay icon.
    • FallbackType.scaffold: Renders a full "Access Denied" page for screens.
    • FallbackType.text: Displays an inline error text widget.
    • Dynamic Fallback Builders: Pass fallbackBuilder: (context, missingRoles, missingPerms) => ... locally on widgets or globally in GuardifyScope.
  • πŸ‘₯ Multi-Role & PBAC Support: Configure roles and fine-grained permissions (requireAll: true/false).
  • 🧭 Route Guard for Navigation: Easily secure routes with GuardifyRouteGuard or guardifyRedirect (compatible with go_router and Navigator).
  • πŸ”‘ Custom Permission Checker: Plug in custom auth callbacks (Firebase Auth, JWT claims, dynamic rules).
  • πŸš€ BuildContext Extensions: Query authorization directly in code using context.hasRole('admin') or context.hasPermission('users:delete').
  • πŸ›‘οΈ Variable Shadowing Immunity: Code generator safely isolates internal variables to avoid any parameter collisions.

πŸš€ Getting Started #

Add Dependencies #

Add guardify to your pubspec.yaml:

dependencies:
  flutter:
    sdk: flutter
  guardify: ^1.2.0

dev_dependencies:
  build_runner: ^2.4.0 # Optional: only needed if using @Secured code generation

Run flutter pub get to install.


πŸ’» Usage #

1. Wrap Your App with GuardifyScope #

Wrap your app or widget tree with GuardifyScope to supply active user roles and permissions:

void main() {
  runApp(
    GuardifyScope(
      currentRole: 'admin',
      currentPermissions: const {'users:delete', 'reports:export'},
      child: const MyApp(),
    ),
  );
}

Reactive Auth Binding with GuardifyScope.listenable

Automatically rebuilds descendant scope widgets whenever your auth notifier changes (no setState required):

GuardifyScope.listenable(
  listenable: authStateNotifier, // ValueNotifier<String?>
  child: const MyApp(),
)

2. Choose Your Gating Mode #

Option A: Zero-Boilerplate Runtime Widget (RoleGate)

No code generation required! Guard any widget directly:

// 1. Silently hide for unauthorized users
RoleGate(
  allowedRoles: const ['admin'],
  child: FloatingActionButton(onPressed: () {}, child: const Icon(Icons.add)),
)

// 2. Disabled mode with lock overlay badge (e.g. Freemium / Pro features)
RoleGate(
  allowedRoles: const ['premium'],
  fallbackType: FallbackType.disabled,
  lockBadge: const CircleAvatar(
    backgroundColor: Colors.black87,
    child: Icon(Icons.lock, color: Colors.amber),
  ),
  child: ElevatedButton(onPressed: exportReport, child: const Text('Export PDF')),
)

// 3. Dynamic context-aware fallback builder
RoleGate(
  allowedRoles: const ['editor'],
  fallbackBuilder: (context, missingRoles, missingPerms) {
    return UpgradeBanner(requiredRole: missingRoles.first);
  },
  child: const EditArticleToolbar(),
)

Option B: Annotation-Based Code Generation (@Secured)

Ideal for design systems, reusable button kits, and enterprise component governance:

part 'my_widgets.secured.g.dart';

@Secured(['admin', 'superadmin'], fallback: FallbackType.hide)
class DeleteUserButton extends StatelessWidget {
  final String userId;
  final VoidCallback onDelete;

  const DeleteUserButton({super.key, required this.userId, required this.onDelete});

  @override
  Widget build(BuildContext context) => ElevatedButton(...);
}

Run build runner to generate .secured.g.dart:

dart run build_runner build --delete-conflicting-outputs

Then instantiate cleanly with zero prop-drilling:

SecuredDeleteUserButton(
  userId: 'usr_100',
  onDelete: () => deleteUser('usr_100'),
);

3. Route & Navigation Guards (go_router / Navigator) #

Prevent unauthorized users from entering protected screens at the router level:

GoRoute(
  path: '/admin',
  redirect: GuardifyRouteGuard(
    allowedRoles: const ['admin'],
    fallbackPath: '/unauthorized',
  ),
  builder: (context, state) => const AdminScreen(),
);

Or perform an inline redirect check:

final redirect = guardifyRedirect(
  context,
  allowedRoles: const ['manager'],
  fallbackPath: '/unauthorized',
);

if (redirect != null) {
  // Handle redirect or show notification
}

4. BuildContext Extensions #

Use BuildContext helper extensions anywhere in your widget tree:

// Role checks
if (context.hasRole('admin')) { ... }
if (context.hasAnyRole(['admin', 'manager'])) { ... }
if (context.hasAllRoles(['manager', 'finance'])) { ... }

// Permission checks (PBAC)
if (context.hasPermission('users:delete')) { ... }
if (context.hasAnyPermission(['reports:view', 'reports:export'])) { ... }
if (context.hasAllPermissions(['posts:read', 'posts:write'])) { ... }

5. Fallback UI Strategies #

Strategy Behavior Typical Use Case
FallbackType.hide (default) Renders const SizedBox.shrink() Inline buttons, list actions
FallbackType.disabled Renders with AbsorbPointer, reduced opacity, & optional lock badge Freemium / Pro features
FallbackType.scaffold Full-screen "Access Denied" page with AppBar Restricted screens / pages
FallbackType.text Renders inline error text message Form fields, tables
fallbackBuilder Dynamic context-aware builder receiving missing roles & permissions Custom upgrade banners

πŸ›‘οΈ Custom Permission Checker Callback #

Connect external authentication engines or custom claim evaluators:

GuardifyScope(
  permissionChecker: (allowedRoles, {requireAll = false, activeRoles, allowedPermissions, activePermissions}) {
    return myAuthService.evaluate(
      allowedRoles: allowedRoles,
      allowedPermissions: allowedPermissions,
    );
  },
  child: const MyApp(),
)

πŸ—ΊοΈ Roadmap #

Check out our detailed ROADMAP.md to explore upcoming features including compliance CLI tools and automated test scopes.


πŸ“„ License #

This project is licensed under the MIT License - see the LICENSE file for details.

1
likes
160
points
93
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

A Dart code generation package for Role-Based UI Access Control in Flutter widgets.

Repository (GitHub)
View/report issues

License

MIT (license)

Dependencies

analyzer, build, code_builder, dart_style, flutter, meta, source_gen

More

Packages that depend on guardify