The Day My App Let Managers Run Wild
Every app has that “uh-oh” moment. Mine came when I realized that managers could:
-
Access WhatsApp notification settings
-
Change geofence boundaries like they were playing Google Maps
-
Edit and delete admin users
-
Promote themselves to admin like it was a medieval Game of Thrones plot
In short, I had created a democracy, and I hated it.
What started as a well-meaning ClockIn system slowly turned into a Manager-Controlled Admin Simulator. And guess who was to blame?
Me. Just me.
My Boss’s Face When I Told Him
Boss: “Why can a sales manager change WhatsApp notification timings?”
Me: “Because… team empowerment?”
Boss: “No.”
Me: “Because I didn’t expect them to actually do it.”
Boss: “Fix it.”
Me: “On it.”
Thus began Operation Digital Bouncer™: a mission to restrict access without offending egos—or accidentally locking myself out in the process.
Step One: Design the “Nope Matrix”
Access control needs structure. So I built this:
Feature | Admin | Manager | Employee |
---|---|---|---|
WhatsApp Settings | ✅ | ❌ | ❌ |
Geofence Management | ✅ | ❌ | ❌ |
System Settings | ✅ | ❌ | ❌ |
User Management | ✅ (Full) | ✅ (Limited) | ❌ |
Role Assignment | ✅ | ❌ | ❌ |
Attendance Management | ✅ | ✅ | ❌ |
Admins: Basically gods.
Managers: Mortal, but with clipboard powers.
Employees: Can clock in, clock out, and pray for payday.
Step Two: Middleware With Muscles
Then came the real fun: backend enforcement. Enter requireManagerUserAccess
, the middleware equivalent of a velvet rope at a tech conference.
if (req.user.role === 'manager') {
// Managers can't create or edit admins
if ((req.method === 'POST' || req.method === 'PUT') && req.body.role === 'admin') {
return res.status(403).json({ success: false, message: 'Managers cannot create or modify admin users.' });
}
// Managers can't touch admin records
const [targetUser] = await pool.execute('SELECT role FROM users WHERE id = ?', [req.params.id]);
if (targetUser[0]?.role === 'admin') {
return res.status(403).json({ success: false, message: 'Managers cannot manage admin users.' });
}
}
If managers even think about becoming admins, this function shows up and says:
“Sir, I’m going to need you to back away from that role dropdown.”
Step Three: Frontend Shenanigans
No good backend is complete without a frontend safety net. I filtered routes like a barista filtering decaf customers at 9 PM.
const adminMenuItems = allAdminMenuItems.filter(item => item.roles.includes(user?.role));
Managers now only see what they’re supposed to.
No more “click to chaos” moments.
It’s like decluttering your garage. Now they only see the toolbox, not the nuclear reactor hiding behind it.
Custom Access Denied Pages: Sass Included
Of course, people will still try to sneak in via direct URLs. So I gave them the gift of style:
<Alert severity="error">
<Typography variant="h6">Access Denied</Typography>
<Typography>You don’t have permission to access WhatsApp settings. Only administrators can manage WhatsApp notifications.</Typography>
</Alert>
Translation:
“Nice try, but no. Don’t make me write this in all caps.”
I considered using memes. But HR said no. (Spoil sports.)
Step Four: Lock Down User Management
Here’s where things got delicate. Managers needed to manage users—but not admin users.
So I set rules like a paranoid older sibling:
-
Hide the “admin” option in role dropdowns
-
Block edit buttons for admins
-
Add a “View Only” chip as a subtle digital slap
{isManager && user.role === 'admin' && (
<Chip label="View Only" color="default" variant="outlined" />
)}
It’s like saying:
“You can look, but if you click that, I will revoke your snack privileges.”
Step Five: Backend API Guard Dogs
Even if someone bypasses the frontend (nice try), I added more protection than a medieval castle:
-
All sensitive routes now require
requireAdmin
-
Managers trying to reset admin passwords? 403.
-
Managers trying to delete an admin? 403.
-
Managers trying to promote someone to admin? 403 with a side of judgment.
Testing: Welcome to the Hackathon From Hell
I tested like a bored teenager trying to break curfew:
-
Faked roles in the JWT
-
Hit APIs directly with Postman
-
Pretended to be a rogue manager with admin dreams
Every path I tried failed. It felt good.
I even had a little evil laugh at one point.
Oops Moment: The Import That Wasn’t
I had everything working. Routes, middleware, UI…
Then production threw this at me:
ReferenceError: requireAdmin is not defined
Because I forgot to import the middleware.
That’s right—I locked everyone out, including myself.
Pro tip: always double-check your require()
s before bragging.
The Fallout
After the deployment:
-
Admins: “Nice. Clean. Safe. We love it.”
-
Managers: “Why can’t I click anything anymore?”
-
Me: “Because you’re a manager. That’s literally the point.”
-
Employees: “What’s a WhatsApp setting?”
Perfect.
Lessons Learned (The Hard Way)
-
Access control is like house rules—set them early or suffer later
-
Middleware is where trust goes to die (and be replaced with logic)
-
If it’s not blocked in the backend, it’s not really blocked
-
UI-only security is security theater
-
Don’t forget your imports (seriously, I’ll never recover)
Today’s System: Order Restored
Now:
-
Managers manage people, not power
-
Admins control sensitive features
-
Employees don’t notice anything (which means I did my job right)
-
My phone is quiet and blissfully free of late-night WhatsApp scares
Next up: locking down the office coffee machine. I know someone’s been overriding the brew strength settings.
In case you missed my previous post where i began this system development: