firebase 如何在带有Go Router和RiverPod的Flutter应用程序上使用角色库访问

roqulrg3  于 2023-11-21  发布在  Go
关注(0)|答案(1)|浏览(154)

我有一个Flutter应用程序的基础上这个初学者模板https://github.com/bizz84/starter_architecture_flutter_firebase
如何在此模板上创建基于角色的访问权限?我有一个User模型,它有一个属性String role。如果角色是“admin”,则用户可以访问所有页面。如果角色是“accountant”,则用户不应该访问“/filiais”分支/路由。
我想不出如何用路由器和河荚连接这个。
这是app.dart:

  1. class MyApp extends ConsumerWidget {
  2. const MyApp({super.key});
  3. @override
  4. Widget build(BuildContext context, WidgetRef ref) {
  5. final goRouter = ref.watch(goRouterProvider);
  6. return MaterialApp.router(
  7. routerConfig: goRouter,
  8. theme: ThemeData(
  9. primarySwatch: Colors.deepOrange,
  10. unselectedWidgetColor: Colors.grey,
  11. appBarTheme: const AppBarTheme(
  12. elevation: 2.0,
  13. centerTitle: true,
  14. ),
  15. scaffoldBackgroundColor: Colors.grey[200],
  16. dividerColor: Colors.grey[400],
  17. // https://github.com/firebase/flutterfire/blob/master/packages/firebase_ui_auth/doc/theming.md
  18. outlinedButtonTheme: OutlinedButtonThemeData(
  19. style: ButtonStyle(
  20. backgroundColor: MaterialStateProperty.all<Color>(Colors.indigo),
  21. foregroundColor: MaterialStateProperty.all<Color>(Colors.white),
  22. ),
  23. ),
  24. ),
  25. debugShowCheckedModeBanner: false,
  26. localizationsDelegates: [
  27. FirebaseUILocalizations.withDefaultOverrides(LabelOverrides()),
  28. GlobalMaterialLocalizations.delegate,
  29. GlobalWidgetsLocalizations.delegate,
  30. FirebaseUILocalizations.delegate,
  31. ],
  32. );
  33. }
  34. }

字符串
这是app_router.dart

  1. part 'app_router.g.dart';
  2. // private navigators
  3. final _rootNavigatorKey = GlobalKey<NavigatorState>();
  4. final _estoqueNavigatorKey = GlobalKey<NavigatorState>(debugLabel: 'estoque');
  5. final _filiaisNavigatorKey = GlobalKey<NavigatorState>(debugLabel: 'filiais');
  6. final _pricesNavigatorKey = GlobalKey<NavigatorState>(debugLabel: 'prices');
  7. enum AppRoute {
  8. onboarding,
  9. signIn,
  10. profile,
  11. filiais,
  12. filial,
  13. addFilial,
  14. editFilial,
  15. estoque,
  16. prices
  17. }
  18. @riverpod
  19. // ignore: unsupported_provider_value
  20. GoRouter goRouter(GoRouterRef ref) {
  21. final authRepository = ref.watch(authRepositoryProvider);
  22. final onboardingRepository = ref.watch(onboardingRepositoryProvider);
  23. return GoRouter(
  24. initialLocation: '/signIn',
  25. navigatorKey: _rootNavigatorKey,
  26. debugLogDiagnostics: true,
  27. redirect: (context, state) {
  28. final didCompleteOnboarding = onboardingRepository.isOnboardingComplete();
  29. if (!didCompleteOnboarding) {
  30. // Always check state.subloc before returning a non-null route
  31. // https://github.com/flutter/packages/blob/main/packages/go_router/example/lib/redirection.dart#L78
  32. if (state.location != '/onboarding') {
  33. return '/onboarding';
  34. }
  35. }
  36. final currentUser = authRepository.currentUser;
  37. final isLoggedIn = currentUser != null;
  38. if (isLoggedIn) {
  39. if (state.location.startsWith('/signIn')) {
  40. return '/precos';
  41. }
  42. } else {
  43. if (state.location.startsWith('/precos') ||
  44. state.location.startsWith('/estoque') ||
  45. state.location.startsWith('/filiais')) {
  46. return '/signIn';
  47. }
  48. }
  49. return null;
  50. },
  51. refreshListenable: GoRouterRefreshStream(authRepository.authStateChanges()),
  52. routes: [
  53. GoRoute(
  54. path: '/onboarding',
  55. name: AppRoute.onboarding.name,
  56. pageBuilder: (context, state) => const NoTransitionPage(
  57. child: OnboardingScreen(),
  58. ),
  59. ),
  60. GoRoute(
  61. path: '/signIn',
  62. name: AppRoute.signIn.name,
  63. pageBuilder: (context, state) => const NoTransitionPage(
  64. child: CustomSignInScreen(),
  65. ),
  66. ),
  67. // Stateful navigation based on:
  68. // https://github.com/flutter/packages/blob/main/packages/go_router/example/lib/stateful_shell_route.dart
  69. StatefulShellRoute.indexedStack(
  70. builder: (context, state, navigationShell) {
  71. return ScaffoldWithNestedNavigation(navigationShell: navigationShell);
  72. },
  73. branches: [
  74. StatefulShellBranch(
  75. navigatorKey: _pricesNavigatorKey,
  76. routes: [
  77. GoRoute(
  78. path: '/precos',
  79. name: AppRoute.prices.name,
  80. pageBuilder: (context, state) => const NoTransitionPage(
  81. child: PricesScreen(),
  82. ),
  83. ),
  84. ],
  85. ),
  86. StatefulShellBranch(
  87. navigatorKey: _estoqueNavigatorKey,
  88. routes: [
  89. GoRoute(
  90. path: '/estoque',
  91. name: AppRoute.estoque.name,
  92. pageBuilder: (context, state) => const NoTransitionPage(
  93. child: EstoqueScreen(),
  94. ),
  95. ),
  96. ],
  97. ),
  98. // this branch is not accountant related, accountants should not see this
  99. StatefulShellBranch(
  100. navigatorKey: _filiaisNavigatorKey,
  101. routes: [
  102. GoRoute(
  103. path: '/filiais',
  104. name: AppRoute.filiais.name,
  105. pageBuilder: (context, state) => const NoTransitionPage(
  106. child: FiliaisScreen(),
  107. ),
  108. routes: [
  109. GoRoute(
  110. path: 'add',
  111. name: AppRoute.addFilial.name,
  112. parentNavigatorKey: _rootNavigatorKey,
  113. pageBuilder: (context, state) {
  114. return const MaterialPage(
  115. fullscreenDialog: true,
  116. child: EditFilialScreen(),
  117. );
  118. },
  119. ),
  120. GoRoute(
  121. path: ':id',
  122. name: AppRoute.editFilial.name,
  123. pageBuilder: (context, state) {
  124. final filialId = state.pathParameters['id'];
  125. final filial = state.extra as Filial?;
  126. return MaterialPage(
  127. fullscreenDialog: true,
  128. child: EditFilialScreen(filialId: filialId, filial: filial),
  129. );
  130. }),
  131. ],
  132. ),
  133. ],
  134. ),
  135. ],
  136. ),
  137. ],
  138. //errorBuilder: (context, state) => const NotFoundScreen(),
  139. );
  140. }


我还没有尝试过任何东西,因为我无法理解如何处理这个问题。

xkftehaa

xkftehaa1#

您的isLoggedIn检查有一个良好的开端!这是我如何修改它以满足您的要求。

  1. if (isLoggedIn) {
  2. if (state.location.startsWith('/signIn')) {
  3. return '/precos';
  4. }
  5. if (state.location.startsWith('/filiais') && currentUser.role == 'accountant') {
  6. return 'path_to_wherever_you_want_the_accountants_redirected';
  7. }
  8. }

字符串
使用state.location.contains()而不是state.location.startsWith()可能是个好主意。我不知道你的路由是如何设置的,但contains会捕获更多包含“/filiais”的路由。

相关问题