MCCodes - Chapter 8: Staff Panel & Permissions
Welcome to Chapter 8! In Chapter 7: Cron Job System, we learned how MCCodes automates background tasks like refilling energy and processing jail times using scheduled jobs. Now, let's switch gears and look at how game administrators (or "staff") manage the game itself using the Staff Panel.
The Problem: Who Runs the Game?
Imagine a game with no one in charge. Who fixes problems? Who adds new items or features? Who makes sure players aren't cheating? A game needs administrators or "Staff Members" with special tools to manage players, items, settings, and more.
But we can't just give everyone these powerful tools! We need a separate, secure area for staff and a way to control which staff members can do which actions. For example, maybe a junior moderator can only read player reports, while a senior admin can edit any player's account.
The Solution: MCCodes provides a dedicated Staff Panel -- a private administrative backend -- and a Permissions System to control access within it.
- Staff Panel: Think of this as the game's "control room". It's a separate section of the game website where staff members can access tools to monitor and manage the game world.
- Permissions System: This is like the security system for the control room. It uses "roles" (like keycards) to define what different staff members are allowed to do.
The Control Room: staff.php
and sglobals.php
The main entry point to the staff area is typically staff.php
. When a staff member accesses this page or any other page within the staff panel (like staff_users.php
to manage users, or staff_items.php
to manage items), a special setup file called sglobals.php
runs first.
sglobals.php
: The Staff Setup
Remember globals.php
from Chapter 2: Global Setup & Session Management? It sets up everything for regular players. sglobals.php
is very similar, but it's specifically for staff pages. It does things like:
- Session & Basic Setup: Starts the session, connects to the database (
$db
), loads site settings ($set
), and loads the logged-in user's data ($ir
). - Staff Check: Crucially, it verifies that the current user is actually a staff member. If not, it stops loading the page immediately. This prevents regular players from accessing staff tools. It uses a helper function,
is_staff()
, for this check. - Staff Page Structure: It initializes the page builder object (
$h
) from Chapter 1: Page Rendering & Structure and uses a special method,$h->smenuarea()
, to display the staff menu (smenu.php
) instead of the regular game menu.
Here's a highly simplified conceptual look at part of sglobals.php
:
<?php
// File: sglobals.php (Simplified Concept)
// ... (Session start, DB connection, load $set, load $ir) ...
require 'global_func.php'; // Contains is_staff() and check_access()
// *** Staff Check ***
// is_staff() checks if the user has any role assigned in the users_roles table
if (!is_staff())
{
echo 'This page cannot be accessed.<br />> <a href="index.php">Go Home</a>';
die; // Stop execution if not staff
}
// ... (Check level, etc.) ...
// --- Initialize Page Builder for Staff ---
require 'header.php';
$h = new headers();
if (!isset($nohdr) || !$nohdr) {
$h->startheaders();
// ... (Display user data) ...
$h->smenuarea(); // <--- Loads the STAFF menu (smenu.php)
}
?>
The key difference from globals.php
is the is_staff()
check and loading the smenu.php
navigation.
staff.php
: The Gatekeeper
The staff.php
file itself often acts as the main dashboard or router for the staff panel. It might display some general information (like in the default MCCodes setup) or check the action
parameter in the URL (staff.php?action=some_action
) to include the correct staff_*.php
file to handle that specific task.
For example, a request to staff_users.php?action=edituser
might be handled directly by staff_users.php
, or it might be routed through staff.php
which then includes the relevant part of staff_users.php
. The core idea is that sglobals.php
runs first to secure the area and set up the environment.
Keycards and Permissions: staff_roles
and check_access()
Okay, so sglobals.php
makes sure only staff can get into the control room. But how do we control which buttons they can press once inside?
- Analogy: Imagine the control room has different sections: User Management, Item Management, Game Settings. You need specific keycards (Roles) to unlock the doors to each section.
MCCodes uses a Role-Based Access Control (RBAC) system:
Roles (
staff_roles
table): This table defines the different "keycards" or job titles available (e.g., "Moderator", "Assistant", "Administrator"). More importantly, it defines what permissions each role grants. Each permission is usually a simple Yes/No (boolean) column in the table.- Example
staff_roles
columns:-
id
(Unique Role ID) -
name
(e.g., "Moderator") -
manage_users
(Boolean: 1 for Yes, 0 for No) -
manage_items
(Boolean: 1 for Yes, 0 for No) -
view_logs
(Boolean: 1 for Yes, 0 for No) -
manage_punishments
(Boolean: 1 for Yes, 0 for No) -
administrator
(Boolean: If 1, grants ALL permissions) - ... and many more specific permissions.
-
- Example
User Roles (
users_roles
table): This table links users to roles. It simply stores pairs ofuserid
andstaff_role
(the ID from thestaff_roles
table). A user can have multiple roles.- Example
users_roles
entry:userid=5, staff_role=3
(User 5 has the role with ID 3).
- Example
The Bouncer (
check_access()
function): This crucial function, usually found inglobal_func.php
, acts like the security guard checking your keycard at each section door.- Input: It takes the permission needed (e.g.,
'manage_users'
) and optionally the user ID to check (defaults to the currently logged-in user). - Process:
- It looks up the user's role IDs from the
users_roles
table. - For each role the user has, it fetches the permissions granted by that role from the
staff_roles
table. - It checks if any of the user's roles grant the specific permission requested (i.e., if the corresponding column is
1
or if theadministrator
column is1
).
- It looks up the user's role IDs from the
- Output: Returns
true
if access is granted,false
otherwise.
- Input: It takes the permission needed (e.g.,
Here's a simplified conceptual look at check_access()
:
<?php
// File: global_func.php (Simplified Concept)
/**
* Checks if a user has a specific permission based on their assigned roles.
* @param string|array $permissions The permission name(s) required (e.g., 'manage_users').
* @param int|null $target_id The user ID to check (null for current user).
* @return bool True if access granted, False otherwise.
*/
function check_access(string|array $permissions, ?int $target_id = null): bool
{
global $db, $userid;
$target_id ??= (int)$userid; // Use current user if not specified
// 1. Get the user's role IDs from users_roles table
$q_user_roles = $db->query("SELECT staff_role FROM users_roles WHERE userid = {$target_id}");
$user_role_ids = [];
while ($row = $db->fetch_row($q_user_roles)) {
$user_role_ids[] = $row['staff_role'];
}
$db->free_result($q_user_roles);
if (empty($user_role_ids)) {
return false; // No roles assigned
}
// 2. Get all permissions granted by these roles from staff_roles table
$q_role_perms = $db->query("SELECT * FROM staff_roles WHERE id IN (" . implode(',', $user_role_ids) . ")");
$granted_permissions = [];
while ($role_data = $db->fetch_row($q_role_perms)) {
if ($role_data['administrator']) {
return true; // Admins have all permissions!
}
foreach ($role_data as $perm_name => $is_granted) {
// Add permission if granted (value is 1) and not already added
if ($is_granted && !in_array($perm_name, $granted_permissions) && !in_array($perm_name, ['id', 'name'])) {
$granted_permissions[] = $perm_name;
}
}
}
$db->free_result($q_role_perms);
// 3. Check if the required permission(s) are in the granted list
if (is_string($permissions)) {
$permissions = [$permissions]; // Make it an array if single string
}
// Convert requested permissions to DB column format (lowercase, underscores)
$requested_db_perms = array_map(fn($p) => strtolower(str_replace([' ', '-'], '_', $p)), $permissions);
$matches = array_intersect($granted_permissions, $requested_db_perms);
return !empty($matches); // Access granted if there's at least one match
}
/**
* Checks if the current user has any staff role.
* @return bool True if staff, False otherwise.
*/
function is_staff(): bool
{
global $db, $userid;
$q = $db->query("SELECT COUNT(*) FROM users_roles WHERE staff_role > 0 AND userid = {$userid}");
return $db->fetch_single($q) > 0;
}
?>
How It Works: Accessing a Staff Feature
Let's tie it all together. Imagine a staff member with the "Moderator" role (which grants manage_punishments
but not manage_items
) tries to access the "Add Item" page.
- Navigate: The Moderator clicks a link in the staff menu (
smenu.php
). Maybe they manually typestaff_items.php?action=newitem
into the address bar. - Setup: The server starts running
staff_items.php
. The first line includessglobals.php
. - Staff Check (
sglobals.php
):sglobals.php
runs. It checks the session, connects to the DB, loads the Moderator's data ($ir
), and callsis_staff()
. Since the Moderator is staff, this check passes.sglobals.php
finishes, and the staff menu is displayed. Permission Check (
staff_items.php
): Control returns tostaff_items.php
. Inside the code block that handles thenewitem
action, the first thing it does is check the specific permission required:<?php // File: staff_items.php (Simplified Concept for 'newitem' action) require_once('sglobals.php'); // Already ran, user is verified as staff // ... other code ... // Specific action: Adding a new item if ($_GET['action'] == 'newitem') { // *** Permission Check *** if (!check_access('manage_items')) { // Moderator does NOT have 'manage_items' permission echo 'You cannot access this area.<br />> <a href="staff.php">Go Back</a>'; $h->endpage(); exit; // Stop execution } // --- If check passes, show the form --- echo "<h3>Adding an item...</h3>"; // ... (code to display the 'Add Item' form) ... } // ... other actions like edititem, etc. ... ?>
Access Denied: The
check_access('manage_items')
function is called for the Moderator.- It finds the Moderator's role ID(s).
- It fetches the permissions for the "Moderator" role from
staff_roles
. - It sees that the
manage_items
column for the Moderator role is0
(or false). -
check_access()
returnsfalse
.
Stop Execution: The
if
condition(!check_access(...))
becomes true. The script prints the "You cannot access this area" message, calls$h->endpage()
, and usesexit
to stop running immediately. The Moderator never sees the "Add Item" form.
If an Administrator (whose role has administrator=1
or manage_items=1
) accessed the same page, check_access('manage_items')
would return true
, the if
condition would be false, and the script would continue to display the form.
Sequence Diagram: Accessing a Staff Page
sequenceDiagram participant B as Browser (Staff User) participant S as Server (staff_items.php) participant SG as sglobals.php participant CA as check_access() participant DB as Database B->>S: Request staff_items.php?action=newitem S->>SG: require 'sglobals.php' SG->>DB: Connect, Load Settings, Load User ($ir) SG->>CA: Call is_staff() CA->>DB: SELECT COUNT(*) FROM users_roles WHERE userid=X AND staff_role > 0 DB-->>CA: Return count (e.g., 1) CA-->>SG: Return true SG->>S: Finish sglobals.php setup (display staff menu) S->>S: Reaches code for action='newitem' S->>CA: Call check_access('manage_items') CA->>DB: Get user's roles (SELECT staff_role FROM users_roles WHERE userid=X) DB-->>CA: Return role IDs (e.g., [3]) CA->>DB: Get permissions for roles (SELECT * FROM staff_roles WHERE id IN (3)) DB-->>CA: Return role data (e.g., {'manage_users': 1, 'manage_items': 0, ...}) CA->>CA: Check if 'manage_items' is granted (No) CA-->>S: Return false S->>S: Access denied branch executes S-->>B: Display "You cannot access this area." message S->>S: exit()
This shows how sglobals.php
verifies the user is staff, and then the specific page (staff_items.php
) uses check_access()
to verify the specific permission needed for that action before proceeding.
Key Files & Tables
- Files:
-
staff.php
: Main entry point/dashboard for the Staff Panel. -
sglobals.php
: Setup file for staff pages (checks staff status, loads staff menu). Similar toglobals.php
(Chapter 2: Global Setup & Session Management). -
smenu.php
: Defines the navigation links within the Staff Panel. Included byheader.php
(Chapter 1: Page Rendering & Structure) when$h->smenuarea()
is called. -
staff_*.php
(e.g.,staff_users.php
,staff_items.php
,staff_shops.php
): Files containing the logic for specific staff actions. They includesglobals.php
and usecheck_access()
. -
global_func.php
: Usually contains thecheck_access()
andis_staff()
helper functions.
-
- Tables:
-
staff_roles
: Defines the available roles and the permissions (boolean flags) granted by each. -
users_roles
: Links users (userid
) to roles (staff_role
). -
stafflog
: Records actions performed by staff members for auditing purposes.stafflog_add()
function is used to write to this table.
-
Conclusion
You've now learned how MCCodes provides a secure and flexible way for administrators to manage the game!
- The Staff Panel (
staff.php
,staff_*.php
) is the dedicated administrative backend. -
sglobals.php
acts as the entry guard, ensuring only staff members can access it and setting up the staff environment (including the staff menusmenu.php
). - The Permissions System uses Roles (defined in
staff_roles
) and User-Role assignments (inusers_roles
) to control access. - The
check_access()
function is used within staff pages to verify if the current staff member has the specific permission required for the action they are attempting.
This system allows for granular control over staff capabilities, ensuring that different staff members have access only to the tools appropriate for their responsibilities.
Managing a game involves not just adding features and controlling access, but also ensuring the security and integrity of the system itself. How does MCCodes protect against common web vulnerabilities and handle sensitive data like passwords?
Next Up: Chapter 9: Security Functions (CSRF/Password/Validation)
Previously: Chapter 7: Cron Job System
First published April 21, 2025
Tags: MCCodes Walkthrough Tutorial