From c3fba4baa45a4777e7daf829423cd58a68abe6da Mon Sep 17 00:00:00 2001
From: "google-labs-jules[bot]"
<161369871+google-labs-jules[bot]@users.noreply.github.com>
Date: Sun, 6 Sep 2026 14:13:56 +0000
Subject: [PATCH] feat: implement reusable authentication-gating system
Co-authored-by: omharde42 <193398705+omharde42@users.noreply.github.com>
---
server/src/routes/post.routes.ts | 16 +++++--
server/src/routes/tournament.routes.ts | 16 +++++--
web/next-env.d.ts | 3 +-
web/src/app/auth/login/page.tsx | 31 +++++++++----
web/src/app/auth/register/page.tsx | 26 ++++++++---
web/src/app/settings/page.tsx | 59 +++++++++++++-----------
web/src/components/auth/require-auth.tsx | 49 ++++++++++++++++++++
web/src/hooks/useAuth.ts | 29 +++++++++++-
web/tsconfig.json | 2 +-
9 files changed, 173 insertions(+), 58 deletions(-)
create mode 100644 web/src/components/auth/require-auth.tsx
diff --git a/server/src/routes/post.routes.ts b/server/src/routes/post.routes.ts
index 4fd5c0c..ac7fbf7 100644
--- a/server/src/routes/post.routes.ts
+++ b/server/src/routes/post.routes.ts
@@ -1,16 +1,22 @@
import { Router } from 'express';
import { postController } from '../controllers/post.controller';
-import { authenticate } from '../middleware/auth';
+import { authenticate, optionalAuth } from '../middleware/auth';
import { uploadMedia } from '../middleware/upload';
+
const router = Router();
-router.get('/trending', authenticate, postController.getTrending);
-router.get('/', authenticate, postController.list);
-router.get('/:id', authenticate, postController.getById);
+
+// Public / optional auth read endpoints
+router.get('/trending', optionalAuth, postController.getTrending);
+router.get('/', optionalAuth, postController.list);
+router.get('/:id', optionalAuth, postController.getById);
+router.get('/:id/comments', optionalAuth, postController.getComments);
+
+// Protected mutation endpoints
router.post('/', authenticate, postController.create);
router.post('/upload', authenticate, uploadMedia, postController.uploadMedia);
router.post('/poll/vote', authenticate, postController.votePoll);
router.delete('/:id', authenticate, postController.delete);
router.post('/:id/like', authenticate, postController.like);
-router.get('/:id/comments', authenticate, postController.getComments);
router.post('/:id/comment', authenticate, postController.comment);
+
export default router;
diff --git a/server/src/routes/tournament.routes.ts b/server/src/routes/tournament.routes.ts
index 1dea184..ed03cd2 100644
--- a/server/src/routes/tournament.routes.ts
+++ b/server/src/routes/tournament.routes.ts
@@ -1,6 +1,6 @@
import { Router } from 'express';
import { tournamentController } from '../controllers/tournament.controller';
-import { authenticate } from '../middleware/auth';
+import { authenticate, optionalAuth } from '../middleware/auth';
import { validate } from '../middleware/validate';
import {
createTournamentValidation,
@@ -10,15 +10,23 @@ import {
disputeValidation,
resolveDisputeValidation,
} from '../validators/tournament';
+
const router = Router();
+
+// Protected user-specific list
router.get('/my', authenticate, tournamentController.myTournaments.bind(tournamentController));
-router.get('/', authenticate, tournamentController.list.bind(tournamentController));
-router.get('/:id', authenticate, tournamentIdParamValidation, validate, tournamentController.getById.bind(tournamentController));
-router.get('/:id/standings', authenticate, tournamentIdParamValidation, validate, tournamentController.getStandings.bind(tournamentController));
+
+// Public / optional auth read endpoints
+router.get('/', optionalAuth, tournamentController.list.bind(tournamentController));
+router.get('/:id', optionalAuth, tournamentIdParamValidation, validate, tournamentController.getById.bind(tournamentController));
+router.get('/:id/standings', optionalAuth, tournamentIdParamValidation, validate, tournamentController.getStandings.bind(tournamentController));
+
+// Protected mutation endpoints
router.post('/', authenticate, createTournamentValidation, validate, tournamentController.create.bind(tournamentController));
router.post('/:id/register', authenticate, registerTournamentValidation, validate, tournamentController.registerTeam.bind(tournamentController));
router.post('/:id/brackets', authenticate, tournamentIdParamValidation, validate, tournamentController.generateBrackets.bind(tournamentController));
router.post('/:id/matches/:matchId/result', authenticate, submitResultValidation, validate, tournamentController.submitResult.bind(tournamentController));
router.post('/:id/matches/:matchId/disputes', authenticate, disputeValidation, validate, tournamentController.fileDispute.bind(tournamentController));
router.patch('/:id/disputes/:disputeId', authenticate, resolveDisputeValidation, validate, tournamentController.resolveDispute.bind(tournamentController));
+
export default router;
diff --git a/web/next-env.d.ts b/web/next-env.d.ts
index 830fb59..ce4e94a 100644
--- a/web/next-env.d.ts
+++ b/web/next-env.d.ts
@@ -1,6 +1,7 @@
///