패키지, 저장소 및 앱 카테고리 검색

패키지 상세v3.2.1

permission_policy

역할 기반 접근 제어, 계층적 권한 및 사용자 정의 가능한 UI 컴포넌트를 갖춘 플러터 앱을 위한 유연하고 강력한 권한 관리 시스템입니다.

AndroidiOSmacOS
30일 다운로드
166
좋아요
26
Pub 점수
160

패키지 설치

flutter pub add permission_policy

패키지 개요

공개 정보를 바탕으로 생성한 선택 가이드입니다.

PermissionPolicy는 Flutter 앱을 위한 강력한 권한 관리 시스템으로, 역할 기반 접근 제어 및 계층적 권한을 지원합니다. 사용자 액세스를 동적으로 관리할 수 있는 사용자 정의 가능한 UI 컴포넌트를 제공합니다. 보안에 신경 쓰는 애플리케이션을 위해 설계되었으며 Android, iOS, macOS를 지원하여 개발자가 앱 내 특정 작업을 수행할 수 있는 사용자를 세밀하게 제어할 수 있도록 합니다. 기존 워크플로우와 원활하게 통합되며 구조화된 권한 로직을 통해 앱 보안을 강화합니다.

사용 사례

  • 관리자 패널에서 사용자 역할 관리
  • 민감한 기능에 대한 액세스 제어
  • 다중 계층 사용자 액세스 구현
  • 백엔드 API 호출 보호
  • 앱 수준 권한 관리
  • 런타임 시 정책 규칙 강제 적용

주요 기능

  • 역할 기반 접근 제어
  • 계층적 권한 구조
  • 사용자 정의 가능한 UI 구성 요소
  • 크로스 플랫폼 지원 (Android, iOS, macOS)
  • 동적 권한 평가
  • Flutter 앱과의 간편한 통합

적합한 대상

  • 기업용 플러터 애플리케이션
  • 엄격한 접근 제어가 필요한 앱
  • 사용자 역할이 있는 관리 대시보드
  • 보안 중심 모바일 앱
  • 유연한 권한 시스템이 필요한 개발자
  • 복잡한 사용자 계층을 관리하는 팀

고려 사항

  • 사전에 역할과 권한을 정의해야 합니다
  • 사용자 정의 UI 조정이 필요할 수 있습니다
  • 권한 계층 구조의 올바른 설정에 달려 있음
  • 정의된 액세스 레벨을 가진 앱에 가장 적합
  • 동적 정책을 위한 추가 구성
  • 간단한 1명 사용자 앱에는 적합하지 않음

원본 README

연결된 소스 저장소의 README 원문 스냅샷입니다. 최신 내용은 저장소에서 확인하세요.

Permission Policy for Flutter

pub package License: MIT

A powerful and flexible permission management system for Flutter applications with device-level role-based access control (RBAC), hierarchical permissions, and customizable UI components.

Features

  • Type-safe models - Permission and Role with full serialization support
  • Hierarchical permissions - Permissions can inherit from other permissions
  • Role inheritance - Roles can inherit permissions from other roles
  • Device-level roles - Assign roles directly to the device — no user identity required
  • Detailed results - PermissionResult includes the reason, contributing roles, and permissions
  • Pluggable storage - Implement PermissionStorage for any backend (default uses Nylo local storage)
  • Performance caching - Resolved permissions are cached and automatically invalidated on changes
  • UI components - PermissionGuard, PermissionBuilder, and RoleSelector

Getting Started

Installation

Add to your pubspec.yaml:

dependencies:
  permission_policy: ^3.2.1

Or with the Dart CLI:

flutter pub add permission_policy
Basic Setup
import 'package:permission_policy/permission_policy.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  // Initialize
  await PermissionPolicy.instance.initialize();

  // Define permissions and roles
  await PermissionPolicy.instance.configure(
    permissions: [
      Permission(id: 'read_posts', name: 'Read Posts'),
      Permission(id: 'write_posts', name: 'Write Posts'),
      Permission(id: 'delete_posts', name: 'Delete Posts'),
    ],
    roles: [
      Role(id: 'viewer', name: 'Viewer', permissions: ['read_posts']),
      Role(id: 'editor', name: 'Editor', permissions: ['read_posts', 'write_posts']),
      Role(id: 'admin', name: 'Admin', permissions: ['read_posts', 'write_posts', 'delete_posts']),
    ],
  );

  // Assign a role to the device
  await PermissionPolicy.instance.giveRole('editor');

  runApp(MyApp());
}
Simple Configuration

For quick setups you can use a map of role names to permission IDs:

await PermissionPolicy.instance.configureSimple({
  'admin': ['read_posts', 'write_posts', 'delete_posts'],
  'editor': ['read_posts', 'write_posts'],
  'viewer': ['read_posts'],
});

Core Concepts

Permissions

A Permission represents a specific action or access right. Permissions can inherit from other permissions using inheritsFrom - granting a permission automatically includes its parents.

Permission(
  id: 'edit_profile',
  name: 'Edit Profile',
  description: 'Can edit user profile information',
  category: 'user',
  priority: 2,
  inheritsFrom: ['view_profile'], // Also grants view_profile
  metadata: {'icon': 'edit'},
)
Property Type Description
id String Unique identifier (required)
name String Human-readable name (required)
description String? What this permission allows
category String? Grouping category
priority int Priority level (default 0)
inheritsFrom List<String> Parent permission IDs to inherit
metadata Map<String, dynamic> Custom metadata
Roles

A Role groups permissions together and can inherit from other roles. Use isAssignable to control whether a role appears in selectors, and isSystem to mark roles that shouldn't be deleted.

Role(
  id: 'moderator',
  name: 'Moderator',
  description: 'Can moderate content',
  permissions: ['edit_posts', 'delete_posts'],
  inheritsFrom: ['editor'], // Inherits all editor permissions
  priority: 5,
  isAssignable: true,
  isSystem: false,
)
Property Type Description
id String Unique identifier (required)
name String Human-readable name (required)
description String? Role description
priority int Priority level (default 0)
permissions List<String> Directly assigned permission IDs
inheritsFrom List<String> Parent role IDs to inherit from
isAssignable bool Can be assigned (default true)
isSystem bool System role flag (default false)
metadata Map<String, dynamic> Custom metadata
Permission Resolution

Permissions are resolved purely through roles. The device has a list of role IDs, and the system resolves all permissions by walking the role and permission inheritance chains.

API Reference

Checking Permissions
final policy = PermissionPolicy.instance;

// Simple boolean check
bool canEdit = await policy.hasPermission('edit_posts');

// Check any of multiple permissions
bool canManage = await policy.hasAnyPermission(['edit_posts', 'delete_posts']);

// Check all permissions are granted
bool fullAccess = await policy.hasAllPermissions(['read_posts', 'write_posts', 'delete_posts']);
Detailed Permission Results

Use checkPermission to get a PermissionResult with the reason and contributing factors:

PermissionResult result = await policy.checkPermission('edit_posts');

print(result.granted);                // true or false
print(result.reason);                 // e.g. 'Permission granted through roles'
print(result.contributingRoles);      // e.g. ['editor']
print(result.contributingPermissions); // e.g. ['edit_posts']

// Also available for multiple checks
PermissionResult anyResult = await policy.checkAnyPermission(['edit_posts', 'delete_posts']);
PermissionResult allResult = await policy.checkAllPermissions(['read_posts', 'write_posts']);
Managing Roles
// Give a role to the device
await policy.giveRole('editor');

// Remove a role
await policy.removeRole('editor');

// Check roles
bool isAdmin = await policy.hasRole('admin');
bool hasEditAccess = await policy.hasAnyRole(['editor', 'admin']);
bool isSuperMod = await policy.hasAllRoles(['moderator', 'admin']);

// Get the device's roles
List<String> roleIds = await policy.getDeviceRoles();

// Get all available roles
List<Role> allRoles = await policy.getRoles();

// Get only assignable roles (isAssignable == true)
List<Role> assignable = await policy.getAssignableRoles();

// Get all resolved permissions for the device
Set<String> allPermissions = await policy.getDevicePermissions();

// Clear all device roles
await policy.clearRoles();

// Clear everything (permissions, roles, and device roles)
await policy.clearAll();

Widgets

PermissionGuard

Conditionally renders a widget based on permissions or roles. Shows the child when granted and the fallback when denied.

PermissionGuard(
  permissions: ['edit_posts'],
  child: ElevatedButton(
    onPressed: () => editPost(),
    child: Text('Edit Post'),
  ),
  fallback: Text('You cannot edit this post'),
)

Guard by roles:

PermissionGuard(
  roles: ['admin', 'moderator'],
  checkType: PermissionCheck.any, // Device needs ANY of these roles
  child: AdminPanel(),
)
Property Type Description
permissions List<String>? Permission IDs to check
roles List<String>? Role IDs to check
checkType PermissionCheck .all (default) or .any
child Widget Widget shown when granted (required)
fallback Widget? Widget shown when denied
loading Widget? Widget shown while checking
onPermissionChecked Function(PermissionResult)? Callback with result
showDebugInfo bool Show debug tooltip in debug mode (default false)
PermissionBuilder

A builder pattern that gives you full control over the widget tree based on permission state.

PermissionBuilder(
  permissions: ['delete_posts'],
  builder: (context, hasPermission, result) {
    return ElevatedButton(
      onPressed: hasPermission ? () => deletePost() : null,
      style: ElevatedButton.styleFrom(
        backgroundColor: hasPermission ? Colors.red : Colors.grey,
      ),
      child: Text(hasPermission ? 'Delete' : 'Cannot Delete'),
    );
  },
)
Property Type Description
permissions List<String>? Permission IDs to check
roles List<String>? Role IDs to check
checkType PermissionCheck .all (default) or .any
builder Widget Function(BuildContext, bool, PermissionResult?) Builder function (required)
loading Widget? Widget shown while checking
RoleSelector

An interactive role selection widget with three display styles: list, chips, and cards.

// List style (default)
RoleSelector(
  style: const RoleSelectorStyle.list(),
  onRoleChanged: (role, isSelected) {
    if (isSelected) {
      PermissionPolicy.instance.giveRole(role.id);
    } else {
      PermissionPolicy.instance.removeRole(role.id);
    }
  },
)

// Chip style
RoleSelector(
  style: const RoleSelectorStyle.chips(),
  multiSelect: true,
  showDescriptions: true,
)

// Card grid style
RoleSelector(
  style: const RoleSelectorStyle.cards(
    crossAxisCount: 3,
    selectedColor: Colors.blue,
  ),
)
Property Type Description
style RoleSelectorStyle .list(), .chips(), or .cards()
onRoleChanged Function(Role, bool)? Called when a role is toggled
onSelectionComplete Function(List<Role>)? Called with all selected roles
multiSelect bool Allow multiple selection (default true)
initialSelectedRoleIds List<String> Pre-selected role IDs
itemBuilder Widget Function(Role, bool, VoidCallback)? Custom item builder
roleFilter bool Function(Role)? Filter which roles to display
showDescriptions bool Show role descriptions (default true)
loading Widget? Loading widget
emptyWidget Widget? Widget when no roles available

RoleSelectorStyle supports customizing spacing, selectedColor, backgroundColor, titleStyle, subtitleStyle, scrollPhysics, and for cards: crossAxisCount and childAspectRatio.

Advanced Usage

Permission Inheritance

Build hierarchical permission structures where higher-level permissions automatically include lower-level ones:

await PermissionPolicy.instance.configure(
  permissions: [
    Permission(id: 'view_content', name: 'View Content'),
    Permission(
      id: 'edit_content',
      name: 'Edit Content',
      inheritsFrom: ['view_content'], // Includes view
    ),
    Permission(
      id: 'publish_content',
      name: 'Publish Content',
      inheritsFrom: ['edit_content'], // Includes edit AND view
    ),
  ],
  roles: [
    Role(id: 'author', name: 'Author', permissions: ['edit_content']),
    Role(
      id: 'publisher',
      name: 'Publisher',
      inheritsFrom: ['author'], // Inherits author's permissions
      permissions: ['publish_content'],
    ),
  ],
);

A device with the publisher role will have: publish_content, edit_content, and view_content.

Custom Storage

Implement PermissionStorage to use any backend (database, API, shared preferences, etc.):

class ApiPermissionStorage implements PermissionStorage {
  @override
  Future<void> initialize() async {
    // Connect to your API
  }

  @override
  Future<void> storePermissions(List<Permission> permissions) async { ... }

  @override
  Future<List<Permission>> getPermissions() async { ... }

  @override
  Future<Permission?> getPermission(String id) async { ... }

  @override
  Future<void> storeRoles(List<Role> roles) async { ... }

  @override
  Future<List<Role>> getRoles() async { ... }

  @override
  Future<Role?> getRole(String id) async { ... }

  @override
  Future<void> storeDeviceRoles(List<String> roleIds) async { ... }

  @override
  Future<List<String>> getDeviceRoles() async { ... }

  @override
  Future<void> clearDeviceRoles() async { ... }

  @override
  Future<void> clear() async { ... }
}

// Use it
final policy = PermissionPolicy.createWithStorage(ApiPermissionStorage());
Testing

Use PermissionPolicy.reset() in test setup to start fresh:

import 'package:flutter_test/flutter_test.dart';
import 'package:permission_policy/permission_policy.dart';

void main() {
  setUp(() async {
    PermissionPolicy.reset();
    await PermissionPolicy.instance.initialize();

    await PermissionPolicy.instance.configureSimple({
      'admin': ['read', 'write', 'delete'],
      'viewer': ['read'],
    });
  });

  test('editor can write', () async {
    await PermissionPolicy.instance.giveRole('admin');

    expect(await PermissionPolicy.instance.hasPermission('write'), isTrue);
  });

  testWidgets('guard shows content with permission', (tester) async {
    await PermissionPolicy.instance.giveRole('viewer');

    await tester.pumpWidget(
      MaterialApp(
        home: PermissionGuard(
          permissions: const ['read'],
          child: const Text('Content'),
          fallback: const Text('Denied'),
        ),
      ),
    );

    await tester.pumpAndSettle();
    expect(find.text('Content'), findsOneWidget);
  });
}

Changelog

Please see CHANGELOG for more information on what has changed recently.

Social

Licence

The MIT License (MIT). Please view the License File for more information.

카테고리

의존성

의존성 목록 1 개

  • nylo_support^7.27.4

소스 저장소

이 패키지를 사용하는 프로젝트

아직 데이터가 없습니다.