From a2eee8aee7d2c93fa4459a960dffa5f64803f15d Mon Sep 17 00:00:00 2001
From: Akshay
Date: Sat, 15 Nov 2025 16:40:06 +0530
Subject: [PATCH 1/3] feat(dashboard): Implement role-based access control for
company resources
- Add userRole extraction from useCompanyContext hook across all company dashboard pages
- Implement canManageEvents permission check based on user role (owner, admin, editor)
- Conditionally render "Create Event" button and link only for users with manage permissions
- Update event page descriptions to reflect user permissions (manage vs view-only)
- Hide action column in events table for users without management permissions
- Restrict event deletion, editing, and preview actions to authorized users
- Apply same role-based pattern to hackathons and team management pages
- Update empty state messaging based on user permissions and search context
- Enhance TeamManagement component with role-based visibility controls
- Improve CompanyDashboard with permission-aware feature access
---
app/dashboard/company/[slug]/events/page.tsx | 138 ++++++++++--------
.../company/[slug]/hackathons/page.tsx | 58 +++++---
app/dashboard/company/[slug]/page.tsx | 18 ++-
app/dashboard/company/[slug]/team/page.tsx | 8 +-
components/dashboard/CompanyDashboard.tsx | 34 +++--
components/dashboard/TeamManagement.tsx | 4 +-
6 files changed, 155 insertions(+), 105 deletions(-)
diff --git a/app/dashboard/company/[slug]/events/page.tsx b/app/dashboard/company/[slug]/events/page.tsx
index 886d8bca..949d75e7 100644
--- a/app/dashboard/company/[slug]/events/page.tsx
+++ b/app/dashboard/company/[slug]/events/page.tsx
@@ -25,13 +25,15 @@ import {
} from '@/components/ui/alert-dialog'
export default function CompanyEventsPage() {
- const { currentCompany, loading: companyLoading } = useCompanyContext()
+ const { currentCompany, userRole, loading: companyLoading } = useCompanyContext()
const isPendingInvitation = usePendingInvitationRedirect()
const [events, setEvents] = useState([])
const [loading, setLoading] = useState(true)
const [searchTerm, setSearchTerm] = useState('')
const [deletingEventSlug, setDeletingEventSlug] = useState(null)
+ const canManageEvents = userRole && ['owner', 'admin', 'editor'].includes(userRole)
+
const fetchEvents = useCallback(async () => {
if (!currentCompany) return
@@ -170,15 +172,17 @@ export default function CompanyEventsPage() {
Events
- Manage your company's events and hackathons
+ {canManageEvents ? "Manage your company's events and hackathons" : "View your company's events"}
-
-
-
+ {canManageEvents && (
+
+
+
+ )}
{/* Stats Cards */}
@@ -239,7 +243,7 @@ export default function CompanyEventsPage() {
All Events ({filteredEvents.length})
- View and manage all your events
+ {canManageEvents ? 'View and manage all your events' : 'View all company events'}
@@ -254,10 +258,10 @@ export default function CompanyEventsPage() {
No events found
- {searchTerm ? 'Try adjusting your search' : 'Get started by creating your first event'}
+ {searchTerm ? 'Try adjusting your search' : canManageEvents ? 'Get started by creating your first event' : 'No events available yet'}
- Manage your team members, roles, and permissions
+ {canManageTeam
+ ? 'Manage your team members, roles, and permissions'
+ : 'View your team members and their roles'}
)
diff --git a/components/dashboard/CompanyDashboard.tsx b/components/dashboard/CompanyDashboard.tsx
index 76f167aa..a7d03833 100644
--- a/components/dashboard/CompanyDashboard.tsx
+++ b/components/dashboard/CompanyDashboard.tsx
@@ -22,6 +22,7 @@ import {
} from 'lucide-react'
import { Company } from '@/types/company'
import { format, formatDistanceToNow } from 'date-fns'
+import { useCompanyContext } from '@/contexts/CompanyContext'
interface CompanyDashboardStats {
totalEvents: number
@@ -63,12 +64,17 @@ interface CompanyDashboardProps {
}
export function CompanyDashboard({ company }: CompanyDashboardProps) {
+ const { userRole } = useCompanyContext()
const [stats, setStats] = useState(null)
const [recentActivity, setRecentActivity] = useState([])
const [upcomingEvents, setUpcomingEvents] = useState([])
const [loading, setLoading] = useState(true)
const [error, setError] = useState(null)
+ // Check permissions based on role
+ const canManageEvents = userRole && ['owner', 'admin', 'editor'].includes(userRole)
+ const canManageTeam = userRole && ['owner', 'admin'].includes(userRole)
+
const fetchDashboardData = useCallback(async () => {
try {
setLoading(true)
@@ -342,18 +348,22 @@ export function CompanyDashboard({ company }: CompanyDashboardProps) {
-
-
+ {canManageEvents && (
+
+ )}
+ {canManageTeam && (
+
+ )}
Team Members
- Manage your team members and their roles
+ {canManageTeam
+ ? 'Manage your team members and their roles'
+ : 'View your team members and their roles'}
{canManageTeam && (
From 5c7d9c5a7d753629851e81afaacae45e911d27ba Mon Sep 17 00:00:00 2001
From: Akshay
Date: Sat, 15 Nov 2025 16:52:50 +0530
Subject: [PATCH 2/3] feat(subscription): Enhance subscription page access
control and messaging
- Update page metadata title to "Subscription" and refine description
- Replace hard redirect with conditional access control check for non-owners/admins
- Implement dynamic page heading based on user permissions (Management vs Information)
- Add conditional description text that reflects user's subscription access level
- Allow all authenticated members to view subscription information while restricting management capabilities to owners and admins
---
.../company/[slug]/subscription/page.tsx | 18 ++++++++++--------
1 file changed, 10 insertions(+), 8 deletions(-)
diff --git a/app/dashboard/company/[slug]/subscription/page.tsx b/app/dashboard/company/[slug]/subscription/page.tsx
index 9af77795..89750561 100644
--- a/app/dashboard/company/[slug]/subscription/page.tsx
+++ b/app/dashboard/company/[slug]/subscription/page.tsx
@@ -5,8 +5,8 @@ import { companyService } from '@/lib/services/company-service'
import { SubscriptionManagement } from '@/components/subscription/SubscriptionManagement'
export const metadata: Metadata = {
- title: 'Subscription Management | CodeUnia',
- description: 'Manage your company subscription and billing',
+ title: 'Subscription | CodeUnia',
+ description: 'View your company subscription and billing information',
}
interface PageProps {
@@ -59,17 +59,19 @@ export default async function SubscriptionPage({ params }: PageProps) {
redirect('/dashboard/company')
}
- // Only owners and admins can manage subscription
- if (!['owner', 'admin'].includes(membership.role)) {
- redirect(`/dashboard/company/${slug}`)
- }
+ // Check if user can manage subscription
+ const canManageSubscription = ['owner', 'admin'].includes(membership.role)
return (
- Manage your subscription plan and view usage details
+ {canManageSubscription
+ ? 'Manage your subscription plan and view usage details'
+ : 'View your company subscription plan and usage details'}
From ec24f7a453d657c6cb81be4564da978e312cfe9a Mon Sep 17 00:00:00 2001
From: Akshay
Date: Sat, 15 Nov 2025 17:13:32 +0530
Subject: [PATCH 3/3] feat(access-control): restrict company profile edit to
owners/admins and display role
Add conditional rendering for edit button based on user role and show user role in sidebar
---
app/dashboard/company/[slug]/page.tsx | 16 +++++++++-------
components/dashboard/CompanySidebar.tsx | 6 +++---
2 files changed, 12 insertions(+), 10 deletions(-)
diff --git a/app/dashboard/company/[slug]/page.tsx b/app/dashboard/company/[slug]/page.tsx
index 8e3c7381..0d2a7d24 100644
--- a/app/dashboard/company/[slug]/page.tsx
+++ b/app/dashboard/company/[slug]/page.tsx
@@ -164,13 +164,15 @@ export default function CompanySlugDashboardPage() {