TechReizen

Multi-tier study trip portal and role-based access platform for UCLL Technologie

LaravelLaravelPHP 8.2PHP 8.2MySQLMySQLBladeBladeBootstrapBootstrapSCRUMSCRUM
Framework Core
Laravel 11 (PHP 8.2+)
Access Control
Custom RBAC Middleware
Asset Bundling
Vite & Bootstrap Sass

Project context

TechReizen is a web portal built for the UCLL technology department (Internationalisering - Studiereizen) to coordinate international study trips for final-year electronics and ICT students.

The platform coordinates logistics between organizers, accompanying faculty, and participating students by enforcing strict role segregation across all routes, registration steps, and dashboard views.

Multi-tier role architecture and RBAC middleware

The application uses custom Laravel middleware (UserAccess) to inspect authenticated user roles and guard access to specialized section controllers:

Role Target route Controller handler Dashboard functionality
Admin /admin/home HomeController@adminHome Global trip configuration, user account management, and guest code generation
Guide /guide/home HomeController@guideHome Trip itinerary monitoring, student roster tracking, and announcement dispatch
Traveller /traveller/home HomeController@travellerHome Personal travel documents, medical disclosure status, and itinerary details
Guest / HomeController@index Public landing portal and initial invitation code verification

Middleware implementation

Access control is enforced at the HTTP layer via route middleware parameters:

View PHP implementation: UserAccess middleware & route protection
namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;

class UserAccess
{
    public function handle(Request $request, Closure $next, string $userType): Response
    {
        if (auth()->check() && auth()->user()->role === $userType) {
            return $next($request);
        }

        abort(403, 'Unauthorized access to restricted role dashboard.');
    }
}
// routes/web.php
Route::middleware(['auth', 'user-access:traveller'])->group(function () {
    Route::get('/traveller/home', [HomeController::class, 'travellerHome'])->name('traveller.home');
    Route::get('/traveller/trips', [TripController::class, 'myTrips'])->name('traveller.trips');
});

Route::middleware(['auth', 'user-access:guide'])->group(function () {
    Route::get('/guide/home', [HomeController::class, 'guideHome'])->name('guide.home');
    Route::get('/guide/roster/{trip}', [GuideController::class, 'viewRoster'])->name('guide.roster');
});

Route::middleware(['auth', 'user-access:admin'])->group(function () {
    Route::get('/admin/home', [HomeController::class, 'adminHome'])->name('admin.home');
    Route::resource('/admin/trips', AdminTripController::class);
});

Key technical implementations

1. Multi-step participant registration with institutional validation

To prevent unauthorized registrations, the application validates Belgian UCLL student numbers (R, U, or B prefix followed by 7 digits) and automatically completes the institutional email address:

View PHP implementation: ParticipantRegistrationController
namespace App\Http\Controllers;

use App\Models\ParticipantProfile;
use Illuminate\Http\Request;

class ParticipantRegistrationController extends Controller
{
    public function storeStepOne(Request $request)
    {
        $validated = $request->validate([
            'student_number' => ['required', 'string', 'regex:/^[rRuUbB]\d{7}$/'],
            'first_name' => ['required', 'string', 'max:50'],
            'last_name' => ['required', 'string', 'max:50'],
            'study_program_id' => ['required', 'exists:study_programs,id'],
            'trip_id' => ['required', 'exists:trips,id']
        ]);

        $prefix = strtoupper($validated['student_number'][0]);
        $emailDomain = match ($prefix) {
            'R' => '@student.ucll.be',
            'U' => '@ucll.be',
            default => ''
        };

        $validated['institutional_email'] = strtolower($validated['student_number']) . $emailDomain;
        $request->session()->put('registration.step1', $validated);

        return redirect()->route('register.step2');
    }
}

2. Seeded development environments

The project includes automated seeders (CreateUsersSeeder) generating predefined accounts for rapid role testing:

  • admin@testing.test (Admin privileges)
  • guide@testing.test (Guide/Faculty privileges)
  • traveller@testing.test (Student participant privileges)

3. Vite asset pipeline and styling

Assets compile using laravel-vite-plugin with Bootstrap 5.2 Sass styling, ensuring fast hot module replacement (HMR) during local development and lightweight minified bundles for production deployments.