Роли и права доступа

Navigo — это современный роутер для одностраничных приложений (SPA) на JavaScript, обеспечивающий гибкое управление маршрутами. При разработке сложных приложений часто требуется разграничение доступа к определённым страницам или функционалу на основе ролей пользователей. Navigo предоставляет инструменты, позволяющие реализовать контроль доступа на уровне маршрутов, интегрируя его с пользовательской системой аутентификации.


Настройка маршрутов с проверкой ролей

Каждый маршрут в Navigo можно определять с помощью метода on(), передавая путь и колбэк-функцию:

import Navigo from 'navigo';

const router = new Navigo('/', { hash: true });

router.on('/dashboard', () => {
  console.log('Dashboard загружен');
});

Для реализации контроля доступа необходимо добавить проверку роли пользователя перед выполнением колбэка. Обычно роли хранятся в объекте текущего пользователя:

const currentUser = {
  username: 'ivan',
  role: 'admin'
};

Проверку роли можно интегрировать прямо в колбэк маршрута:

router.on('/admin', () => {
  if (currentUser.role !== 'admin') {
    router.navigate('/unauthorized');
    return;
  }
  console.log('Доступ к панели администратора разрешён');
});

Ключевой момент: маршруты могут иметь разные уровни доступа, и проверка роли должна выполняться до выполнения основного кода страницы.


Универсальная функция проверки доступа

Для упрощения управления большим числом маршрутов удобно создать универсальную функцию:

function authorizeRoute(requiredRoles, callback) {
  if (requiredRoles.includes(currentUser.role)) {
    callback();
  } else {
    router.navigate('/unauthorized');
  }
}

Использование такой функции делает маршруты компактными:

router.on('/settings', () => {
  authorizeRoute(['admin', 'editor'], () => {
    console.log('Настройки загружены');
  });
});

Динамические маршруты и роли

Navigo поддерживает динамические сегменты в URL, что позволяет создавать маршруты с параметрами:

router.on('/profile/:userId', (params) => {
  console.log(`Просмотр профиля пользователя с ID: ${params.userId}`);
});

Для контроля доступа к динамическим страницам можно расширить проверку:

router.on('/profile/:userId', (params) => {
  authorizeRoute(['admin'], () => {
    console.log(`Администратор просматривает профиль ${params.userId}`);
  });
});

В этом примере только пользователи с ролью admin смогут просматривать чужие профили. Остальные будут перенаправлены на страницу /unauthorized.


Группировка маршрутов по ролям

Если приложение имеет большое количество маршрутов с одинаковыми правами доступа, удобно создавать группы маршрутов:

const adminRoutes = [
  '/admin',
  '/users',
  '/settings'
];

adminRoutes.forEach(route => {
  router.on(route, () => {
    authorizeRoute(['admin'], () => {
      console.log(`Доступ к ${route} разрешён`);
    });
  });
});

Такой подход минимизирует дублирование кода и упрощает поддержку системы прав доступа.


Асинхронная проверка прав доступа

В реальных приложениях роли пользователя часто загружаются с сервера. Navigo позволяет использовать асинхронные функции для проверки прав:

async function getUserRole() {
  const response = await fetch('/api/user-role');
  const data = await response.json();
  return data.role;
}

router.on('/admin', async () => {
  const role = await getUserRole();
  if (role !== 'admin') {
    router.navigate('/unauthorized');
    return;
  }
  console.log('Доступ разрешён');
});

Особенность: асинхронные проверки должны завершаться до рендеринга страницы, чтобы предотвратить кратковременный показ запрещённого контента.


Управление перенаправлениями

Важной частью системы ролей является маршрутизация на страницы ошибок или страницы входа. Navigo позволяет легко настроить глобальное перенаправление:

router.notFound(() => {
  router.navigate('/not-found');
});

router.on('/unauthorized', () => {
  console.log('Доступ запрещён');
});

Такой механизм обеспечивает централизованное управление случаями, когда пользователь пытается перейти на страницу, для которой у него нет прав.


Комбинирование с middleware

Для комплексных приложений удобно использовать концепцию middleware, оборачивая маршруты в функцию промежуточной проверки:

function withAuth(requiredRoles, routeCallback) {
  return () => {
    if (requiredRoles.includes(currentUser.role)) {
      routeCallback();
    } else {
      router.navigate('/unauthorized');
    }
  };
}

router.on('/admin', withAuth(['admin'], () => {
  console.log('Админский маршрут активен');
}));

Преимущество middleware-подхода — возможность переиспользовать проверку прав доступа для любого маршрута без дублирования кода.


Рекомендации по организации системы прав

  1. Ясная структура ролей — лучше заранее определить все возможные роли и уровни доступа.
  2. Централизованная проверка — использовать одну функцию проверки прав доступа для всех маршрутов.
  3. Группы маршрутов — объединять маршруты по уровням доступа для удобства поддержки.
  4. Асинхронные проверки — учитывать задержки при загрузке ролей с сервера.
  5. Редиректы при запрете доступа — всегда направлять пользователя на страницу unauthorized или login.

Эти подходы позволяют построить масштабируемую систему ролей в Navigo, где управление доступом становится простым, безопасным и поддерживаемым при росте приложения.