我有一个Flutter应用程序的基础上这个初学者模板https://github.com/bizz84/starter_architecture_flutter_firebase
如何在此模板上创建基于角色的访问权限?我有一个User模型,它有一个属性String role。如果角色是“admin”,则用户可以访问所有页面。如果角色是“accountant”,则用户不应该访问“/filiais”分支/路由。
我想不出如何用路由器和河荚连接这个。
这是app.dart:
class MyApp extends ConsumerWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final goRouter = ref.watch(goRouterProvider);
return MaterialApp.router(
routerConfig: goRouter,
theme: ThemeData(
primarySwatch: Colors.deepOrange,
unselectedWidgetColor: Colors.grey,
appBarTheme: const AppBarTheme(
elevation: 2.0,
centerTitle: true,
),
scaffoldBackgroundColor: Colors.grey[200],
dividerColor: Colors.grey[400],
// https://github.com/firebase/flutterfire/blob/master/packages/firebase_ui_auth/doc/theming.md
outlinedButtonTheme: OutlinedButtonThemeData(
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all<Color>(Colors.indigo),
foregroundColor: MaterialStateProperty.all<Color>(Colors.white),
),
),
),
debugShowCheckedModeBanner: false,
localizationsDelegates: [
FirebaseUILocalizations.withDefaultOverrides(LabelOverrides()),
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
FirebaseUILocalizations.delegate,
],
);
}
}
字符串
这是app_router.dart
part 'app_router.g.dart';
// private navigators
final _rootNavigatorKey = GlobalKey<NavigatorState>();
final _estoqueNavigatorKey = GlobalKey<NavigatorState>(debugLabel: 'estoque');
final _filiaisNavigatorKey = GlobalKey<NavigatorState>(debugLabel: 'filiais');
final _pricesNavigatorKey = GlobalKey<NavigatorState>(debugLabel: 'prices');
enum AppRoute {
onboarding,
signIn,
profile,
filiais,
filial,
addFilial,
editFilial,
estoque,
prices
}
@riverpod
// ignore: unsupported_provider_value
GoRouter goRouter(GoRouterRef ref) {
final authRepository = ref.watch(authRepositoryProvider);
final onboardingRepository = ref.watch(onboardingRepositoryProvider);
return GoRouter(
initialLocation: '/signIn',
navigatorKey: _rootNavigatorKey,
debugLogDiagnostics: true,
redirect: (context, state) {
final didCompleteOnboarding = onboardingRepository.isOnboardingComplete();
if (!didCompleteOnboarding) {
// Always check state.subloc before returning a non-null route
// https://github.com/flutter/packages/blob/main/packages/go_router/example/lib/redirection.dart#L78
if (state.location != '/onboarding') {
return '/onboarding';
}
}
final currentUser = authRepository.currentUser;
final isLoggedIn = currentUser != null;
if (isLoggedIn) {
if (state.location.startsWith('/signIn')) {
return '/precos';
}
} else {
if (state.location.startsWith('/precos') ||
state.location.startsWith('/estoque') ||
state.location.startsWith('/filiais')) {
return '/signIn';
}
}
return null;
},
refreshListenable: GoRouterRefreshStream(authRepository.authStateChanges()),
routes: [
GoRoute(
path: '/onboarding',
name: AppRoute.onboarding.name,
pageBuilder: (context, state) => const NoTransitionPage(
child: OnboardingScreen(),
),
),
GoRoute(
path: '/signIn',
name: AppRoute.signIn.name,
pageBuilder: (context, state) => const NoTransitionPage(
child: CustomSignInScreen(),
),
),
// Stateful navigation based on:
// https://github.com/flutter/packages/blob/main/packages/go_router/example/lib/stateful_shell_route.dart
StatefulShellRoute.indexedStack(
builder: (context, state, navigationShell) {
return ScaffoldWithNestedNavigation(navigationShell: navigationShell);
},
branches: [
StatefulShellBranch(
navigatorKey: _pricesNavigatorKey,
routes: [
GoRoute(
path: '/precos',
name: AppRoute.prices.name,
pageBuilder: (context, state) => const NoTransitionPage(
child: PricesScreen(),
),
),
],
),
StatefulShellBranch(
navigatorKey: _estoqueNavigatorKey,
routes: [
GoRoute(
path: '/estoque',
name: AppRoute.estoque.name,
pageBuilder: (context, state) => const NoTransitionPage(
child: EstoqueScreen(),
),
),
],
),
// this branch is not accountant related, accountants should not see this
StatefulShellBranch(
navigatorKey: _filiaisNavigatorKey,
routes: [
GoRoute(
path: '/filiais',
name: AppRoute.filiais.name,
pageBuilder: (context, state) => const NoTransitionPage(
child: FiliaisScreen(),
),
routes: [
GoRoute(
path: 'add',
name: AppRoute.addFilial.name,
parentNavigatorKey: _rootNavigatorKey,
pageBuilder: (context, state) {
return const MaterialPage(
fullscreenDialog: true,
child: EditFilialScreen(),
);
},
),
GoRoute(
path: ':id',
name: AppRoute.editFilial.name,
pageBuilder: (context, state) {
final filialId = state.pathParameters['id'];
final filial = state.extra as Filial?;
return MaterialPage(
fullscreenDialog: true,
child: EditFilialScreen(filialId: filialId, filial: filial),
);
}),
],
),
],
),
],
),
],
//errorBuilder: (context, state) => const NotFoundScreen(),
);
}
型
我还没有尝试过任何东西,因为我无法理解如何处理这个问题。
1条答案
按热度按时间xkftehaa1#
您的isLoggedIn检查有一个良好的开端!这是我如何修改它以满足您的要求。
字符串
使用
state.location.contains()
而不是state.location.startsWith()
可能是个好主意。我不知道你的路由是如何设置的,但contains
会捕获更多包含“/filiais”的路由。