Skip to content

06 — Routing Map

System: PyroRadius ISP Billing & RADIUS Management
Stack: Laravel 13 · Inertia.js v2 · React 18 · PostgreSQL 16
Last Updated: 2026-07-13


Overview

PyroRadius routes are defined across four files:

File Purpose
routes/web.php All authenticated web application routes
routes/auth.php Login, logout, password reset
routes/portal.php Customer self-service portal (separate auth guard)
routes/api.php AJAX/API endpoints consumed by the frontend

All web routes (except auth routes) are wrapped in the auth middleware group. Role and permission enforcement is handled inside controllers using $this->authorize() or Gate::allows() checks, not at the route level. This keeps the route file clean and centralises access logic.


Middleware Groups

Group Name Middleware Applied Used On
web EncryptCookies, AddQueuedCookies, VerifyCsrfToken, ShareErrorsFromSession, HandleInertiaRequests All web routes
auth Authenticate (redirects to login if unauthenticated) All protected routes
portal Authenticate:portal (portal guard) Customer portal routes
api throttle:api, SubstituteBindings API routes (session auth via Sanctum)

Auth Routes (routes/auth.php)

These routes are not behind the auth middleware — they are publicly accessible (except logout).

Name Method URI Controller@Method Notes
login GET /login AuthController@showLogin Renders Auth/Login Inertia page
login.submit POST /login AuthController@login Validates credentials, starts session
logout POST /logout AuthController@logout Destroys session
password.request GET /forgot-password PasswordResetController@request Renders forgot password page
password.email POST /forgot-password PasswordResetController@email Sends reset link
password.reset GET /reset-password/{token} PasswordResetController@showReset Reset form
password.update POST /reset-password PasswordResetController@update Stores new password

Dashboard Routes

Prefix: / — Middleware: auth

Name Method URI Controller@Method Permission Inertia Component
dashboard GET / DashboardController@index view_dashboard Dashboard/Index
dashboard.online GET /dashboard/online-stats DashboardController@onlineStats view_dashboard — (AJAX JSON)
dashboard.health GET /health HealthController@index view_health Health/Index
dashboard.health.check POST /health/check HealthController@runCheck view_health — (AJAX)

Customer Routes

Prefix: /customers — Middleware: auth

Core CRUD

Name Method URI Controller@Method Permission Inertia Component
customers.index GET /customers CustomerController@index view_customers Customers/Index
customers.create GET /customers/create CustomerController@create create_customers Customers/Create
customers.store POST /customers CustomerController@store create_customers — (redirects)
customers.show GET /customers/{customer} CustomerController@show view_customers Customers/Show
customers.edit GET /customers/{customer}/edit CustomerController@edit edit_customers Customers/Edit
customers.update PUT /customers/{customer} CustomerController@update edit_customers — (redirects)
customers.destroy DELETE /customers/{customer} CustomerController@destroy delete_customers — (redirects)

Customer Actions

Name Method URI Controller@Method Permission Notes
customers.recharge POST /customers/{customer}/recharge CustomerController@recharge recharge_customers Triggers full billing + RADIUS flow
customers.status POST /customers/{customer}/status CustomerController@updateStatus edit_customers Toggle active/suspended/disconnected
customers.ledger GET /customers/{customer}/ledger CustomerController@ledger view_customers Customers/Ledger Inertia page
customers.portal-login POST /customers/{customer}/portal-login CustomerController@generatePortalLink edit_customers Issues a signed portal URL
customers.expiry PUT /customers/{customer}/expiry CustomerController@updateExpiry edit_customers Manually set expiry date
customers.bulk-status POST /customers/bulk-status CustomerController@bulkStatus edit_customers Batch suspend/activate
customers.import GET /customers/import ImportController@showCustomers import_data Import/Customers
customers.import.store POST /customers/import ImportController@importCustomers import_data CSV upload + queue

Billing Routes

Prefix: /billing — Middleware: auth

Invoices

Name Method URI Controller@Method Permission Inertia Component
billing.invoices.index GET /billing/invoices InvoiceController@index view_billing Billing/Invoices/Index
billing.invoices.show GET /billing/invoices/{invoice} InvoiceController@show view_billing Billing/Invoices/Show
billing.invoices.create GET /billing/invoices/create InvoiceController@create create_billing Billing/Invoices/Create
billing.invoices.store POST /billing/invoices InvoiceController@store create_billing
billing.invoices.destroy DELETE /billing/invoices/{invoice} InvoiceController@destroy delete_billing
billing.invoices.pdf GET /billing/invoices/{invoice}/pdf InvoiceController@pdf view_billing PDF download response

Payments

Name Method URI Controller@Method Permission Inertia Component
billing.payments.index GET /billing/payments PaymentController@index view_billing Billing/Payments/Index
billing.payments.show GET /billing/payments/{payment} PaymentController@show view_billing Billing/Payments/Show
billing.payments.receipt GET /billing/payments/{payment}/receipt PaymentController@receipt view_billing PDF receipt download
billing.payments.reverse POST /billing/payments/{payment}/reverse PaymentController@reverse reverse_payments Reversal with reason

Archive

Name Method URI Controller@Method Permission Inertia Component
billing.archive.index GET /billing/archive BillingArchiveController@index view_billing Billing/Archive/Index
billing.archive.show GET /billing/archive/{month} BillingArchiveController@show view_billing Billing/Archive/Show
billing.archive.run POST /billing/archive/run BillingArchiveController@run manage_billing Triggers month-end archive

Batches

Name Method URI Controller@Method Permission Inertia Component
billing.batches.index GET /billing/batches InvoiceBatchController@index view_billing Billing/Batches/Index
billing.batches.create GET /billing/batches/create InvoiceBatchController@create create_billing Billing/Batches/Create
billing.batches.store POST /billing/batches InvoiceBatchController@store create_billing Queues batch generation
billing.batches.show GET /billing/batches/{batch} InvoiceBatchController@show view_billing Billing/Batches/Show

Package Routes

Prefix: /packages — Middleware: auth

Name Method URI Controller@Method Permission Inertia Component
packages.index GET /packages PackageController@index view_packages Packages/Index
packages.create GET /packages/create PackageController@create manage_packages Packages/Create
packages.store POST /packages PackageController@store manage_packages
packages.edit GET /packages/{package}/edit PackageController@edit manage_packages Packages/Edit
packages.update PUT /packages/{package} PackageController@update manage_packages Triggers RadiusService::syncPackage()
packages.destroy DELETE /packages/{package} PackageController@destroy manage_packages Checks no active customers

NAS Routes

Prefix: /nas — Middleware: auth

Name Method URI Controller@Method Permission Inertia Component
nas.index GET /nas NasController@index view_nas Nas/Index
nas.create GET /nas/create NasController@create manage_nas Nas/Create
nas.store POST /nas NasController@store manage_nas
nas.edit GET /nas/{nas}/edit NasController@edit manage_nas Nas/Edit
nas.update PUT /nas/{nas} NasController@update manage_nas
nas.destroy DELETE /nas/{nas} NasController@destroy manage_nas
nas.sessions GET /nas/{nas}/sessions NasController@sessions view_nas Nas/Sessions
nas.disconnect POST /nas/{nas}/sessions/{session}/disconnect NasController@disconnect manage_nas Sends MikroTik API disconnect

OLT Routes

Prefix: /olt — Middleware: auth

Name Method URI Controller@Method Permission Inertia Component
olt.index GET /olt OltController@index view_olt Olt/Index
olt.create GET /olt/create OltController@create manage_olt Olt/Create
olt.store POST /olt OltController@store manage_olt
olt.edit GET /olt/{olt}/edit OltController@edit manage_olt Olt/Edit
olt.update PUT /olt/{olt} OltController@update manage_olt
olt.destroy DELETE /olt/{olt} OltController@destroy manage_olt

WhatsApp Routes

Prefix: /whatsapp — Middleware: auth

Name Method URI Controller@Method Permission Inertia Component
whatsapp.index GET /whatsapp WhatsAppController@index view_whatsapp WhatsApp/Index
whatsapp.outbox GET /whatsapp/outbox WhatsAppController@outbox view_whatsapp WhatsApp/Outbox
whatsapp.templates.index GET /whatsapp/templates WhatsAppController@templates manage_whatsapp WhatsApp/Templates
whatsapp.templates.store POST /whatsapp/templates WhatsAppController@storeTemplate manage_whatsapp
whatsapp.send POST /whatsapp/send WhatsAppController@send manage_whatsapp Manual message send
whatsapp.settings GET /whatsapp/settings WhatsAppController@settings manage_whatsapp WhatsApp/Settings
whatsapp.settings.update PUT /whatsapp/settings WhatsAppController@updateSettings manage_whatsapp

Notification Routes

Prefix: /notifications — Middleware: auth

Name Method URI Controller@Method Permission Inertia Component
notifications.index GET /notifications NotificationController@index view_notifications Notifications/Index
notifications.mark-read POST /notifications/{notification}/read NotificationController@markRead Any authenticated user
notifications.mark-all-read POST /notifications/read-all NotificationController@markAllRead Any authenticated user

Campaign Routes

Prefix: /campaigns — Middleware: auth

Name Method URI Controller@Method Permission Inertia Component
campaigns.index GET /campaigns CampaignController@index manage_campaigns Campaigns/Index
campaigns.create GET /campaigns/create CampaignController@create manage_campaigns Campaigns/Create
campaigns.store POST /campaigns CampaignController@store manage_campaigns Queues campaign dispatch
campaigns.show GET /campaigns/{campaign} CampaignController@show manage_campaigns Campaigns/Show
campaigns.destroy DELETE /campaigns/{campaign} CampaignController@destroy manage_campaigns Only if status=draft

Report Routes

Prefix: /reports — Middleware: auth

Name Method URI Controller@Method Permission Inertia Component
reports.index GET /reports ReportController@index view_reports Reports/Index
reports.revenue GET /reports/revenue ReportController@revenue view_reports Reports/Revenue
reports.customers GET /reports/customers ReportController@customers view_reports Reports/Customers
reports.expiry GET /reports/expiry ReportController@expiry view_reports Reports/Expiry
reports.radius GET /reports/radius ReportController@radius view_reports Reports/Radius
reports.dealer GET /reports/dealer ReportController@dealer view_reports Reports/Dealer
reports.export GET /reports/{type}/export ReportController@export view_reports CSV/Excel download

Settings Routes

Prefix: /settings — Middleware: auth

Name Method URI Controller@Method Permission Inertia Component
settings.general GET /settings SettingsController@general manage_settings Settings/General
settings.general.update PUT /settings SettingsController@updateGeneral manage_settings
settings.company GET /settings/company SettingsController@company manage_settings Settings/Company
settings.company.update PUT /settings/company SettingsController@updateCompany manage_settings
settings.radius GET /settings/radius SettingsController@radius manage_settings Settings/Radius
settings.radius.update PUT /settings/radius SettingsController@updateRadius manage_settings
settings.cron GET /settings/cron CronJobController@index manage_settings Settings/CronJobs
settings.cron.update PUT /settings/cron/{job} CronJobController@update manage_settings Toggle enable/disable

User Management Routes

Prefix: /users — Middleware: auth

Name Method URI Controller@Method Permission Inertia Component
users.index GET /users UserController@index manage_users Users/Index
users.create GET /users/create UserController@create manage_users Users/Create
users.store POST /users UserController@store manage_users
users.edit GET /users/{user}/edit UserController@edit manage_users Users/Edit
users.update PUT /users/{user} UserController@update manage_users
users.destroy DELETE /users/{user} UserController@destroy manage_users Cannot delete self
roles.index GET /roles RoleController@index manage_roles Roles/Index
roles.create GET /roles/create RoleController@create manage_roles Roles/Create
roles.store POST /roles RoleController@store manage_roles
roles.edit GET /roles/{role}/edit RoleController@edit manage_roles Roles/Edit
roles.update PUT /roles/{role} RoleController@update manage_roles

Audit Routes

Prefix: /audit — Middleware: auth

Name Method URI Controller@Method Permission Inertia Component
audit.index GET /audit AuditController@index view_audit Audit/Index
audit.show GET /audit/{log} AuditController@show view_audit Audit/Show
audit.export GET /audit/export AuditController@export view_audit CSV download

Import Routes

Prefix: /import — Middleware: auth

Name Method URI Controller@Method Permission Inertia Component
import.index GET /import ImportController@index import_data Import/Index
import.customers POST /import/customers ImportController@importCustomers import_data
import.packages POST /import/packages ImportController@importPackages import_data
import.logs GET /import/logs ImportController@logs import_data Import/Logs

TR-069 Routes

Prefix: /tr069 — Middleware: auth

Name Method URI Controller@Method Permission Inertia Component
tr069.index GET /tr069 Tr069Controller@index manage_tr069 Tr069/Index
tr069.devices GET /tr069/devices Tr069Controller@devices manage_tr069 Tr069/Devices
tr069.device.show GET /tr069/devices/{device} Tr069Controller@show manage_tr069 Tr069/Device
tr069.provision POST /tr069/devices/{device}/provision Tr069Controller@provision manage_tr069

Graph Routes

Prefix: /graphs — Middleware: auth

Name Method URI Controller@Method Permission Inertia Component
graphs.index GET /graphs GraphController@index view_graphs Graphs/Index
graphs.nas GET /graphs/nas/{nas} GraphController@nas view_graphs Graphs/Nas
graphs.customer GET /graphs/customer/{customer} GraphController@customer view_graphs Graphs/Customer

Ticket Routes

Prefix: /tickets — Middleware: auth

Name Method URI Controller@Method Permission Inertia Component
tickets.index GET /tickets TicketController@index view_tickets Tickets/Index
tickets.create GET /tickets/create TicketController@create create_tickets Tickets/Create
tickets.store POST /tickets TicketController@store create_tickets
tickets.show GET /tickets/{ticket} TicketController@show view_tickets Tickets/Show
tickets.update PUT /tickets/{ticket} TicketController@update edit_tickets Status + assignment
tickets.comment POST /tickets/{ticket}/comments TicketController@comment view_tickets Any authenticated user

Engineer Routes

Prefix: /engineer — Middleware: auth

Name Method URI Controller@Method Permission Inertia Component
engineer.dashboard GET /engineer EngineerController@dashboard engineer_access Engineer/Dashboard
engineer.tasks GET /engineer/tasks EngineerController@tasks engineer_access Engineer/Tasks
engineer.tasks.update PUT /engineer/tasks/{task} EngineerController@updateTask engineer_access

Customer Portal Routes (routes/portal.php)

Guard: portal — Middleware: auth:portal
Prefix: /portal

Name Method URI Controller@Method Notes
portal.login GET /portal/login PortalAuthController@showLogin Token-based or phone/password
portal.login.submit POST /portal/login PortalAuthController@login
portal.logout POST /portal/logout PortalAuthController@logout
portal.dashboard GET /portal/dashboard PortalController@dashboard Customer overview
portal.invoices GET /portal/invoices PortalController@invoices Own invoices only
portal.payments GET /portal/payments PortalController@payments Own payment history
portal.profile GET /portal/profile PortalController@profile Edit contact info
portal.profile.update PUT /portal/profile PortalController@updateProfile

API Routes (routes/api.php)

All API routes use session cookie authentication (Sanctum stateful) with CSRF. No API token required for frontend AJAX calls.

Name Method URI Controller@Method Permission Response
api.customers.search GET /api/customers Api\CustomerController@search view_customers JSON array
api.customers.filter GET /api/customers/filter Api\CustomerController@filter view_customers Paginated JSON
api.nas.traffic GET /api/nas/{nas}/traffic Api\NasController@traffic view_nas JSON (MikroTik + SNMP)
api.nas.online GET /api/nas/{nas}/online Api\NasController@online view_nas JSON session list
api.dashboard.online GET /api/dashboard/online Api\DashboardController@online view_dashboard JSON count + list
api.packages.availability GET /api/packages/{package}/availability Api\PackageController@availability view_packages JSON
api.whatsapp.outbox GET /api/whatsapp/outbox Api\WhatsAppController@outbox view_whatsapp Paginated JSON
api.customers.ledger GET /api/customers/{customer}/ledger Api\CustomerController@ledger view_customers JSON ledger entries
api.invoices.search GET /api/invoices Api\InvoiceController@search view_billing JSON invoices for typeahead
api.radius.status GET /api/radius/{username}/status Api\RadiusController@status view_nas JSON RADIUS entry state
api.health.ping GET /api/health/ping Api\HealthController@ping {"status":"ok"}

Route Model Binding

Laravel's implicit route model binding resolves these models automatically from the {param} in the URI:

Param Model Key
{customer} App\Models\Customer id
{invoice} App\Models\Invoice id
{payment} App\Models\Payment id
{package} App\Models\Package id
{nas} App\Models\Nas id
{olt} App\Models\Olt id
{user} App\Models\User id
{role} App\Models\Role id
{ticket} App\Models\Ticket id
{log} App\Models\AuditLog id