Hackathon Diaries: Building Lets-Collab with Django, React, and Permit.io

This is a submission for the Permit.io Authorization Challenge: API-First Authorization Reimagined What I Built Lets-Collab is a full-stack web application that enables users to collaborate on projects and tasks while enforcing strict access control policies. The app supports two main user roles: Admins (e.g., admin users) can access all resources, including creating projects, managing tasks, and viewing audit logs to track user actions. Members (e.g., newuser): Can list projects, create tasks within those projects, but are restricted from accessing audit logs. Here’s a breakdown of the key features: Project and Task Management: Users can create and list projects and tasks via a clean React frontend. The backend, built with Django and Django REST Framework, exposes APIs (/api/projects/, /api/tasks/, /api/audit_logs/) for managing these resources. Authorization with Permit.io: Integrated Permit.io for externalized authorization. Configured policies in Permit.io to enforce declarative rules: Admins have full access to all resources (*) for all actions (read, create, update, delete). Members can list projects (read on projects), create tasks (create on tasks), but are explicitly denied access to audit logs (audit_logs). Used Permit.check() to dynamically evaluate permissions for each API request, logging allowed actions to an AuditLog model. Audit Logging: Implemented audit logs to track user actions (e.g., project_read, task_create) for transparency and accountability. Only admins can view audit logs, ensuring sensitive data is protected. Frontend with React: Built a responsive UI with React, featuring a Dashboard for managing projects and tasks, and an Access Control Dashboard for admins to view audit logs. Added error handling to gracefully manage permission denials (e.g., “Audit logs are restricted to admins only” for non-admins). Demo Here’s a quick demo of CollabSphere in action: Member Experience (newuser): Log in as newuser (username: newuser, password: 2025DEVChallenge). Navigate to the Dashboard (/): List projects: Successfully displays all projects. Create a task: Successfully adds a task to a selected project. Attempt to create a project: Denied (403 Forbidden), as members cannot create projects. Navigate to the Access Control Dashboard (/access-control): Denied access to audit logs with a message: “Audit logs are restricted to admins only.” Admin Experience (admin): Log in as admin (username: admin, password: 2025DEVChallenge). Navigate to the Dashboard (/): List projects and tasks: Successfully displays all data. Create a project and task: Successfully adds new resources. Navigate to the Access Control Dashboard (/access-control): View audit logs: Successfully displays logs of all user actions (e.g., “User admin performed project_read on projects at [timestamp]”). You can try the live demo here: Deployed URL: https://letscollab-eight.vercel.app/ Test Credentials: Admin: admin / 2025DEVChallenge Member: newuser / 2025DEVChallenge Project Repo The source code for Let's-Collab is available on GitHub, split into two repositories: Backend: https://github.com/kihuni/Lets-Collab-API Contains the Django backend, including the PermitPermission class, API endpoints, and audit logging logic. Frontend: https://github.com/kihuni/Lets-Collab-frontend Contains the React frontend with the Dashboard and Access Control Dashboard components. My Journey Building Lets-Collab for the Permit.io Authorization Challenge was a rollercoaster of learning and problem-solving. Here’s a glimpse into my journey: Starting Point: I began with a basic Django-React app for managing projects and tasks, using a mocked authorization system. The challenge required integrating Permit.io for API-first authorization, which was new to me. Learning Permit.io: I dove into Permit.io’s documentation to understand its Policy Decision Point (PDP) and how to define roles, resources, and policies. Setting up the initial policies (e.g., admin with full access, member with restricted access) was straightforward, but integrating them into Django posed challenges. Challenge 1: Async Issues: The Permit.io SDK’s Permit.check() method is asynchronous, but Django is synchronous by default. I encountered a RuntimeWarning: coroutine 'Permit.check' was never awaited error. I fixed this by using asyncio.run() for development, learning that async_to_sync would be better for production with an async server like Uvicorn. Challenge 2: Policy Misconfiguration: Initially, Permit.check() returned False for all requests, denying access to both admin and newuser. This was due to a mismatch between resource names (projects in the code vs. project in Permit.io) and an incorrect API key. I debugged this by adding detailed logging, aligning resource names, and verifying the API key in Permit.io’s dashboard. Challenge 3: Frontend Linting: My Reac

May 4, 2025 - 09:23
 0
Hackathon Diaries: Building Lets-Collab with Django, React, and Permit.io

This is a submission for the Permit.io Authorization Challenge: API-First Authorization Reimagined

What I Built

Lets-Collab is a full-stack web application that enables users to collaborate on projects and tasks while enforcing strict access control policies. The app supports two main user roles:

  • Admins (e.g., admin users) can access all resources, including creating projects, managing tasks, and viewing audit logs to track user actions.
  • Members (e.g., newuser): Can list projects, create tasks within those projects, but are restricted from accessing audit logs.

members

Here’s a breakdown of the key features:

Project and Task Management:

  • Users can create and list projects and tasks via a clean React frontend.
  • The backend, built with Django and Django REST Framework, exposes APIs (/api/projects/, /api/tasks/, /api/audit_logs/) for managing these resources.

Authorization with Permit.io:

  • Integrated Permit.io for externalized authorization.

Configured policies in Permit.io to enforce declarative rules:

  • Admins have full access to all resources (*) for all actions (read, create, update, delete).
  • Members can list projects (read on projects), create tasks (create on tasks), but are explicitly denied access to audit logs (audit_logs).

  • Used Permit.check() to dynamically evaluate permissions for each API request, logging allowed actions to an AuditLog model.

user permission

Audit Logging:

  • Implemented audit logs to track user actions (e.g., project_read, task_create) for transparency and accountability.
  • Only admins can view audit logs, ensuring sensitive data is protected.

Frontend with React:

  • Built a responsive UI with React, featuring a Dashboard for managing projects and tasks, and an Access Control Dashboard for admins to view audit logs.
  • Added error handling to gracefully manage permission denials (e.g., “Audit logs are restricted to admins only” for non-admins).

Demo

Here’s a quick demo of CollabSphere in action:
Member Experience (newuser):

  • Log in as newuser (username: newuser, password: 2025DEVChallenge).

login

Navigate to the Dashboard (/):

  • List projects: Successfully displays all projects.

list projects

  • Create a task: Successfully adds a task to a selected project.

create

  • Attempt to create a project: Denied (403 Forbidden), as members cannot create projects.

attempt failed

Navigate to the Access Control Dashboard (/access-control):

  • Denied access to audit logs with a message: “Audit logs are restricted to admins only.”

audit failed

Admin Experience (admin):
Log in as admin (username: admin, password: 2025DEVChallenge).

admin

Navigate to the Dashboard (/):
List projects and tasks: Successfully displays all data.

list

Create a project and task: Successfully adds new resources.

added new resource

Navigate to the Access Control Dashboard (/access-control):
View audit logs: Successfully displays logs of all user actions (e.g., “User admin performed project_read on projects at [timestamp]”).

audit_logs

You can try the live demo here:

Deployed URL: https://letscollab-eight.vercel.app/

Test Credentials:

  • Admin: admin / 2025DEVChallenge
  • Member: newuser / 2025DEVChallenge

Project Repo

The source code for Let's-Collab is available on GitHub, split into two repositories:

Backend: https://github.com/kihuni/Lets-Collab-API

Contains the Django backend, including the PermitPermission class, API endpoints, and audit logging logic.

Frontend: https://github.com/kihuni/Lets-Collab-frontend

Contains the React frontend with the Dashboard and Access Control Dashboard components.

My Journey

Building Lets-Collab for the Permit.io Authorization Challenge was a rollercoaster of learning and problem-solving. Here’s a glimpse into my journey:

  • Starting Point: I began with a basic Django-React app for managing projects and tasks, using a mocked authorization system. The challenge required integrating Permit.io for API-first authorization, which was new to me.
  • Learning Permit.io: I dove into Permit.io’s documentation to understand its Policy Decision Point (PDP) and how to define roles, resources, and policies. Setting up the initial policies (e.g., admin with full access, member with restricted access) was straightforward, but integrating them into Django posed challenges.
  • Challenge 1: Async Issues: The Permit.io SDK’s Permit.check() method is asynchronous, but Django is synchronous by default. I encountered a RuntimeWarning: coroutine 'Permit.check' was never awaited error. I fixed this by using asyncio.run() for development, learning that async_to_sync would be better for production with an async server like Uvicorn.

  • Challenge 2: Policy Misconfiguration: Initially, Permit.check() returned False for all requests, denying access to both admin and newuser. This was due to a mismatch between resource names (projects in the code vs. project in Permit.io) and an incorrect API key. I debugged this by adding detailed logging, aligning resource names, and verifying the API key in Permit.io’s dashboard.

  • Challenge 3: Frontend Linting: My React frontend had ESLint no-unused-vars warnings for unused err variables in catch blocks. I fixed this by using err.message to provide specific error messages, improving user experience and code quality.

  • Final Touches: I added input validation in the frontend, visual indicators for expired tasks, and ensured the app was deployable on Render and Vercel. Testing with both admin and newuser confirmed that access control worked as expected.

This journey taught me the importance of externalized authorization, the nuances of integrating async libraries with synchronous frameworks, and the value of clean code practices. Despite the challenges, seeing CollabSphere come together with secure, scalable authorization was incredibly rewarding.

API-First Authorization

The Permit.io Authorization Challenge emphasized API-first authorization, a paradigm where authorization logic is decoupled from the application and managed externally via APIs. Lets-Collab embraces this approach by leveraging Permit.io to enforce access control, aligning with the challenge’s goal of reimagining authorization in an API-first world.

Here’s how Lets-Collab implements API-first authorization:

  • Externalized Authorization with Permit.io: Instead of hardcoding access control logic in the Django backend, I offloaded it to Permit.io. The PermitPermission class calls Permit.check() for each API request, querying Permit.io’s PDP (https://cloudpdp.api.permit.io) to determine if the action is allowed.

Declarative Policies: I defined policies in Permit.io’s dashboard using a declarative model:

  • Roles: admin, member.
  • Resources: projects, tasks, audit_logs.
  • Actions: read, create, update, delete.

Policies: admin gets full access (*), while member is restricted to read on projects and create on tasks, with an explicit deny on audit_logs.

  • Scalability and Flexibility: By using Permit.io, I can update access control policies without changing the application code. For example, adding a new role (e.g., guest) or modifying permissions can be done via Permit.io’s dashboard, making the system scalable and adaptable.
  • Auditability: The app logs allowed actions to the AuditLog model, providing a clear audit trail of user activities, which is crucial for security and compliance in an API-first architecture.

API-first authorization with Permit.io allowed me to focus on building Lets-Collab core features while ensuring robust, maintainable access control. It also highlighted the power of decoupling authorization logic, enabling faster iteration and better security practices.

Conclusion

Lets-Collab demonstrates how API-first authorization can enhance a collaborative platform, ensuring secure and role-based access control with Permit.io. I’m proud of the result and grateful for the learning experience this challenge provided. I hope you enjoy exploring Let's-Collab as much as I enjoyed building it!