# Protecting an Admin-Only Data Import Page

A role-based system must enforce permissions on the server. Hiding a link is helpful navigation, but it does not protect the page.

## Store trusted session values at login

After verifying the password and retrieving the database user:

~~~php
session_regenerate_id(true);
$_SESSION["user_id"] = (int) $user["user_id"];
$_SESSION["role"] = $user["role"];
~~~

The role must come from the database, not from a form field supplied by the user.

## Protect the import page

Place this code before any HTML output:

~~~php
<?php
session_start();

if (!isset($_SESSION["user_id"])) {
    header("Location: login.php");
    exit;
}

if (($_SESSION["role"] ?? "") !== "admin") {
    http_response_code(403);
    exit("You do not have permission to access this page.");
}
~~~

## Protect processing as well as display

The role check must run on the script that processes the uploaded CSV. A user can send a request directly even when the navigation link is hidden.

You may keep the form and processing in one protected file or require the same protection file from both scripts.

## Show navigation by role

~~~php
<?php if (($_SESSION["role"] ?? "") === "admin"): ?>
  <a href="import.php">Import dataset</a>
<?php endif; ?>
~~~

This improves usability but is not the security control.

## Test the access rules

| Test | Expected result |
| --- | --- |
| Logged out user opens import URL | Redirected to login |
| Standard user opens import URL | 403 response |
| Administrator opens import URL | Upload form appears |
| Standard user submits directly | Request rejected |
| Changed browser role field | No effect because role comes from session |

## Check

- [ ] Sessions start before output.
- [ ] Login and role are checked server-side.
- [ ] Processing route repeats the protection.
- [ ] Roles come from stored user records.
- [ ] Tests include direct URL access.
- [ ] Test accounts and data are fictional.