Route Guards
Giriş
Route guard'lar, Nylo Website içinde navigasyon için middleware sağlar. Rota geçişlerini yakalar ve bir kullanıcının sayfaya erişip erişemeyeceğini, başka bir yere yönlendirilip yönlendirilmeyeceğini veya rotaya aktarılan verilerin değiştirilip değiştirilmeyeceğini kontrol etmenize olanak tanır.
Yaygın kullanım senaryoları şunlardır:
- Kimlik doğrulama kontrolleri -- kimliği doğrulanmamış kullanıcıları giriş sayfasına yönlendirme
- Rol tabanlı erişim -- sayfaları yönetici kullanıcılarla sınırlama
- Veri doğrulama -- navigasyondan önce gerekli verilerin mevcut olduğundan emin olma
- Veri zenginleştirme -- rotaya ek veri ekleme
Guard'lar navigasyon gerçekleşmeden önce sırayla yürütülür. Herhangi bir guard handled döndürürse, navigasyon durur (yönlendirme veya iptal ile).
Route Guard Oluşturma
Metro CLI kullanarak bir route guard oluşturun:
metro make:route_guard auth
Bu, bir guard dosyası oluşturur:
import 'package:nylo_framework/nylo_framework.dart';
class AuthRouteGuard extends NyRouteGuard {
AuthRouteGuard();
@override
Future<GuardResult> onBefore(RouteContext context) async {
// Add your guard logic here
return next();
}
}
Guard Yaşam Döngüsü
Her route guard'ın üç yaşam döngüsü metodu vardır:
onBefore
Navigasyon gerçekleşmeden önce çağrılır. Koşulları kontrol ettiğiniz ve navigasyona izin verme, yönlendirme veya iptal etme kararını aldığınız yerdir.
@override
Future<GuardResult> onBefore(RouteContext context) async {
bool isLoggedIn = await Auth.isAuthenticated();
if (!isLoggedIn) {
return redirect(HomePage.path);
}
return next();
}
Dönüş değerleri:
next()-- zincirdeki bir sonraki guard'a devam et veya rotaya yönelredirect(path)-- farklı bir rotaya yönlendirabort()-- navigasyonu tamamen iptal et
onAfter
Başarılı navigasyondan sonra çağrılır. Analitik, günlükleme veya navigasyon sonrası yan etkiler için kullanın.
@override
Future<void> onAfter(RouteContext context) async {
// Log page view
Analytics.trackPageView(context.routeName);
}
onLeave
Kullanıcı bir rotadan ayrılırken çağrılır. Kullanıcının ayrılmasını engellemek için false döndürün.
@override
Future<bool> onLeave(RouteContext context) async {
if (hasUnsavedChanges) {
// Show confirmation dialog
return await showConfirmDialog();
}
return true; // Allow leaving
}
RouteContext
RouteContext nesnesi tüm guard yaşam döngüsü metotlarına iletilir ve navigasyon hakkında bilgi içerir:
| Özellik | Tür | Açıklama |
|---|---|---|
context |
BuildContext? |
Mevcut build context |
data |
dynamic |
Rotaya aktarılan veri |
queryParameters |
Map<String, String> |
URL sorgu parametreleri |
routeName |
String |
Hedef rotanın adı/yolu |
originalRouteName |
String? |
Dönüşümlerden önceki orijinal rota adı |
@override
Future<GuardResult> onBefore(RouteContext context) async {
// Access route information
String route = context.routeName;
dynamic routeData = context.data;
Map<String, String> params = context.queryParameters;
return next();
}
Route Context'i Dönüştürme
Farklı veriyle bir kopya oluşturun:
// Change the data type
RouteContext<User> userContext = context.withData<User>(currentUser);
// Copy with modified fields
RouteContext updated = context.copyWith(
data: enrichedData,
queryParameters: {"tab": "settings"},
);
Guard Eylemleri
next
Zincirdeki bir sonraki guard'a devam et veya bu son guard ise rotaya yönel:
return next();
redirect
Kullanıcıyı farklı bir rotaya yönlendir:
return redirect(LoginPage.path);
Ek seçeneklerle:
return redirect(
LoginPage.path,
data: {"returnTo": context.routeName},
navigationType: NavigationType.pushReplace,
queryParameters: {"source": "guard"},
);
| Parametre | Tür | Varsayılan | Açıklama |
|---|---|---|---|
path |
Object |
zorunlu | Rota yolu dizesi veya RouteView |
data |
dynamic |
null | Yönlendirme rotasına aktarılacak veri |
queryParameters |
Map<String, dynamic>? |
null | Sorgu parametreleri |
navigationType |
NavigationType |
pushReplace |
Navigasyon yöntemi |
result |
dynamic |
null | Döndürülecek sonuç |
removeUntilPredicate |
Function? |
null | Rota kaldırma koşulu |
transitionType |
TransitionType? |
null | Sayfa geçiş türü |
onPop |
Function(dynamic)? |
null | Pop'ta geri çağırma |
abort
Yönlendirme yapmadan navigasyonu iptal et. Kullanıcı mevcut sayfasında kalır:
return abort();
setData
Sonraki guard'lara ve hedef rotaya aktarılacak verileri değiştirin:
@override
Future<GuardResult> onBefore(RouteContext context) async {
User user = await fetchUser();
// Enrich the route data
setData({"user": user, "originalData": context.data});
return next();
}
Route'lara Guard Uygulama
Router dosyanızda bireysel rotalara guard ekleyin:
appRouter() => nyRoutes((router) {
router.route(
HomePage.path,
(_) => HomePage(),
).initialRoute();
// Add a single guard
router.route(
ProfilePage.path,
(_) => ProfilePage(),
routeGuards: [AuthRouteGuard()],
);
// Add multiple guards (executed in order)
router.route(
AdminPage.path,
(_) => AdminPage(),
routeGuards: [AuthRouteGuard(), AdminRoleGuard()],
);
});
Grup Guard'ları
Rota grupları kullanarak birden fazla rotaya aynı anda guard uygulayın:
appRouter() => nyRoutes((router) {
router.route(HomePage.path, (_) => HomePage()).initialRoute();
// All routes in this group require authentication
router.group(() {
return {
'prefix': '/dashboard',
'route_guards': [AuthRouteGuard()],
};
}, (router) {
router.route(DashboardPage.path, (_) => DashboardPage());
router.route(SettingsPage.path, (_) => SettingsPage());
router.route(ProfilePage.path, (_) => ProfilePage());
});
});
Guard Kompozisyonu
Nylo Website, yeniden kullanılabilir kalıplar için guard'ları birleştirme araçları sağlar.
GuardStack
Birden fazla guard'ı tek bir yeniden kullanılabilir guard olarak birleştirin:
final protectedRoute = GuardStack([
AuthRouteGuard(),
VerifyEmailGuard(),
TwoFactorGuard(),
]);
// Use the stack on a route
router.route(
SecurePage.path,
(_) => SecurePage(),
routeGuards: [protectedRoute],
);
GuardStack guard'ları sırayla yürütür. Herhangi bir guard handled döndürürse, kalan guard'lar atlanır.
ConditionalGuard
Bir guard'ı yalnızca belirli bir koşul doğru olduğunda uygulayın:
router.route(
BetaPage.path,
(_) => BetaPage(),
routeGuards: [
ConditionalGuard(
condition: (context) => context.queryParameters.containsKey("beta"),
guard: BetaAccessGuard(),
),
],
);
Koşul false döndürürse, guard atlanır ve navigasyon devam eder.
ParameterizedGuard
Yapılandırma parametreleri alan guard'lar oluşturun:
class RoleGuard extends ParameterizedGuard<List<String>> {
RoleGuard(super.params); // params = allowed roles
@override
Future<GuardResult> onBefore(RouteContext context) async {
User? user = await Auth.user<User>();
if (user == null || !params.contains(user.role)) {
return redirect(UnauthorizedPage.path);
}
return next();
}
}
// Usage
router.route(
AdminPage.path,
(_) => AdminPage(),
routeGuards: [RoleGuard(["admin", "super_admin"])],
);
Örnekler
Kimlik Doğrulama Guard'ı
class AuthRouteGuard extends NyRouteGuard {
AuthRouteGuard();
@override
Future<GuardResult> onBefore(RouteContext context) async {
bool isAuthenticated = await Auth.isAuthenticated();
if (!isAuthenticated) {
return redirect(HomePage.path);
}
return next();
}
}
Parametreli Abonelik Guard'ı
class SubscriptionGuard extends ParameterizedGuard<List<String>> {
SubscriptionGuard(super.params);
@override
Future<GuardResult> onBefore(RouteContext context) async {
User? user = await Auth.user<User>();
bool hasAccess = params.any((plan) => user?.subscription == plan);
if (!hasAccess) {
return redirect(UpgradePage.path, data: {"plans": params});
}
setData({"user": user});
return next();
}
}
// Require premium or pro subscription
router.route(
PremiumPage.path,
(_) => PremiumPage(),
routeGuards: [
AuthRouteGuard(),
SubscriptionGuard(["premium", "pro"]),
],
);
Günlükleme Guard'ı
class LoggingGuard extends NyRouteGuard {
LoggingGuard();
@override
Future<GuardResult> onBefore(RouteContext context) async {
print("Navigating to: ${context.routeName}");
return next();
}
@override
Future<void> onAfter(RouteContext context) async {
print("Arrived at: ${context.routeName}");
}
}