Ready to get started?
Join Adocasts Plus for $8.00/mo, or sign into your account to get access to all of our lessons.
Rolling Our Own Authorization Access Controls
In this lesson, we'll create our own simple authorization access control list. We'll then share this list globally throughout our application by appending it to our HttpContext and sharing it with our Vue application via Inertia.
- Author
- Tom Gobich
- Published
- Jan 31
- Duration
- 6m 55s

Developer, dog lover, and burrito eater. Currently teaching AdonisJS, a fully featured NodeJS framework, and running Adocasts where I post new lessons weekly. Professionally, I work with JavaScript, .Net C#, and SQL Server.
Adocasts
Burlington, KY
Get the Code
Download or explore the source code for this lesson on GitHub
Ready to get started?
Join Adocasts Plus for $8.00/mo, or sign into your account to get access to all of our lessons.
-
Getting Started
-
1.0What Is InertiaJS?Lesson 1.01m 57s
-
1.1What We'll Be BuildingLesson 1.16m 18s
-
1.2Creating Our AdonisJS App With InertiaJSLesson 1.211m 26s
-
1.3Server-Side Rendering (SSR) vs Client-Side Rendering (CSR)Lesson 1.36m 6s
-
1.4Setting Up TailwindCSS, Shadcn-Vue, and Automatic Component ImportsLesson 1.419m 9s
-
-
The Basics
-
2.0The Flow of Pages and Page PropsLesson 2.06m 55s
-
2.1Sharing Data from AdonisJS to Vue via InertiaLesson 2.17m 37s
-
2.2Linking Between Pages & Page State FlowLesson 2.25m 58s
-
2.3The Link Component and Programmatic LinkingLesson 2.38m 32s
-
2.4Global Components and Hydration Mismatch in ActionLesson 2.45m 0s
-
2.5Partial and Lazy Data Loading and EvaluationLesson 2.59m 11s
-
2.6Creating A LayoutLesson 2.66m 55s
-
2.7Default Layouts & Overwriting the Default LayoutLesson 2.76m 0s
-
2.8Specifying Page Titles & Meta TagsLesson 2.88m 59s
-
2.9What Code Can & Can't Be Shared Between AdonisJS & InertiaLesson 2.93m 10s
-
-
Working with Forms
-
3.0Inertia Form BasicsLesson 3.04m 15s
-
Form Validation & Displaying ErrorsLesson 3.16m 47s
-
The useForm HelperLesson 3.28m 0s
-
Common useForm Methods & OptionsLesson 3.34m 23s
-
Creating A FormInput Vue ComponentLesson 3.47m 9s
-
Cross-Site Request Forgery (CSRF) Protection in InertiaJSLesson 3.52m 55s
-
What Are Some of Inertia's LimitationsLesson 3.64m 26s
-
-
Database & Project Scaffolding
-
Understanding Our Database SchemaLesson 4.02m 18s
-
Defining Our Migrations & Foreign KeysLesson 4.113m 48s
-
Defining Our Lucid Models & RelationshipsLesson 4.219m 8s
-
Creating A Lucid Model Mixin for our Organization RelationshipLesson 4.38m 29s
-
Seeding Our Initial Database DataLesson 4.43m 39s
-
Typing Lucid Models in Inertia with DTOsLesson 4.510m 58s
-
Completing Our AppLayout & Navigation BarLesson 4.616m 31s
-
Creating A Toast Message ManagerLesson 4.715m 7s
-
-
Authentication & Onboarding
-
User Registration with InertiaJSLesson 5.08m 37s
-
Splitting Our Routes Between Auth & WebLesson 5.15m 5s
-
Logging Out UsersLesson 5.24m 20s
-
Onboarding Newly Registered UsersLesson 5.322m 31s
-
Logging In Users & Displaying ExceptionsLesson 5.410m 40s
-
Adding the Remember Me TokenLesson 5.55m 45s
-
Forgot Password & Password ResetLesson 5.629m 42s
-
-
The User's Organizations
-
Setting & Loading the User's Active OrganizationLesson 6.012m 42s
-
Listing the User's OrganizationsLesson 6.16m 42s
-
The Form Dialog Component & Adding OrganizationsLesson 6.211m 51s
-
Switching Between OrganizationsLesson 6.32m 56s
-
Creating A UseResourceActions ComposableLesson 6.48m 42s
-
Editing the Active OrganizationLesson 6.57m 0s
-
The Confirm Delete Dialog & Deleting the Active OrganizationLesson 6.618m 24s
-
-
Difficulties, Statuses, & Access Levels
-
Listing & Creating DifficultiesLesson 7.015m 14s
-
Updating DifficultiesLesson 7.14m 44s
-
Confirming & Deleting DifficultiesLesson 7.24m 15s
-
Replacing A Course's Deleted DifficultyLesson 7.316m 31s
-
Reusable VineJS Exists In Organization ValidationLesson 7.43m 38s
-
Sorting Difficulties with Drag & DropLesson 7.59m 21s
-
Creating A Reusable Sorting Vue ComponentLesson 7.64m 1s
-
Replicating Behaviors for Access Levels & StatusesLesson 7.714m 28s
-
-
Courses
-
Modules & Lessons
-
Querying & Listing Sortable Course ModulesLesson 9.014m 43s
-
Creating, Editing, & Deleting Course ModulesLesson 9.115m 57s
-
Creating & Listing Sortable Course LessonsLesson 9.219m 30s
-
Editing & Deleting Course LessonsLesson 9.35m 9s
-
Adding A Publish Date & Time InputLesson 9.48m 20s
-
Patching Tag Changes for our Modules & LessonsLesson 9.58m 42s
-
Storing Module Order Changes from Vue DraggableLesson 9.68m 31s
-
Storing Lesson Order Changes & Handling Cross-Module Drag & DropsLesson 9.715m 44s
-
-
Settings
-
Creating the Settings ShellLesson 10.08m 10s
-
User Profile SettingsLesson 10.16m 58s
-
Allowing Users to Safely Update Their Account EmailLesson 10.210m 39s
-
Alerting Users When Their Account Email Is ChangedLesson 10.34m 35s
-
Account Deletion & Cleaning Dangling OrganizationsLesson 10.410m 6s
-
Updating & Deleting an OrganizationLesson 10.510m 15s
-
-
Organization Members
-
Listing Current Organization MembersLesson 11.08m 25s
-
Sending an Invitation to Join Our OrganizationLesson 11.113m 30s
-
Accepting an Organization InvitationLesson 11.218m 4s
-
Adding the Organization Invite User InterfaceLesson 11.320m 0s
-
Canceling an Organization InviteLesson 11.46m 5s
-
Removing an Organization UserLesson 11.59m 37s
-
Refreshing Partial Page DataLesson 11.65m 17s
-
-
Authorization
-
Rolling Our Own Authorization Access ControlsLesson 12.06m 55s
-
Applying Our Server-Side Authorization ChecksLesson 12.113m 0s
-
Applying Our Authorization UI ChecksLesson 12.26m 23s
-
Setting Up Secondary TailwindCSS Config & CSS File for our Landing PageLesson 12.38m 43s
-
Restricting Login Attempts with Rate LimitingLesson 12.49m 24s
-
Clearing Login Attempt Rate Limits on Password ResetLesson 12.54m 31s
-
-
InertiaJS 2
-
Upgrading to Inertia 2Lesson 13.011m 53s
-
Polling for Changes in InertiaJS 2Lesson 13.14m 12s
-
Prefetching Page to Boost Load Times in InertiaJS 2Lesson 13.211m 26s
-
Defer Loading Props in InertiaJS 2Lesson 13.35m 55s
-
Deferring A Prop Load Until it is Visible in InertiaJS 2Lesson 13.44m 27s
-
Super Easy Infinite Scroll in InertiaJS 2 with Prop MergingLesson 13.511m 9s
-
Join The Discussion! (2 Comments)
Please sign in or sign up for free to join in on the dicussion.
emilien
Hi again Tom !
Sorry I ask a lot of questions 😅
I was wondering how I could implement a more granular permission system where a user can have different roles at different levels - for example, being an admin at the org level but only a member for a course and an admin for another one within that workspace. First I would have to create another action
GetCourseAbilities
and create "rules" like we did forGetOrganizationAbilities
.My problem is to understand how to modify the middleware to get the roleId associated to the course. Since we only get the roleId for the workspace. Should I create a middleware that specifically check the
ctx.params
to retrieve thecourse.id
and find the user's role like we do in theworkspace_middleware
?I should have tested it before asking you, but I have analysis paralysis and I'm not sure this is the best and cleaner idea.
Also I was wondering how we can check more things than just the user's role for an organization's ability. For example, canceling an invite. An admin user can cancel all invites, but a member user cannot remove invites, unless he's the one who made the invite. Tried multiple things here but none of them is working. I think I didn't understand very well how things work 😅
Please sign in or sign up for free to reply
tomgobich
Hi Emilien!
No worries at all!! 😊
Yeah, things spiral here quickly depending on your approach. It's a big enough of a topic to be a series of its own, but I'll try to give an overview below.
Access Determination
So, the first thing you need to do is figure out how the more granular access will be determined. Will only the creator have permission to edit, update, and delete? Or, maybe the creator can invite others to edit, update, and delete? Essentially, how are the different roles going to be determined at those different levels?
Creator Only
If it's just the creator, then that's much easier. You'd want to capture the
userId
of the user who created the resource. For example, adding aownerId
onto theCourse
model. Then, you'd handle the logic very similarly to how we allow org members to remove themselves throughout the next two lessons (12.1 & 12.2). By giving priority to allow the action if theownerId
matches the authenticated user's id. When that's the case, you'd want to ignore whatever the role's permission says and allow the action.Resource Specific Invitations
If you want to allow the creator to invite/share with others to collaborate, you'll need a table to track that. This table could look many different ways.
It could be a single table per resource, ex:
course_user
consisting ofcourse_id
,user_id
, androle_id
if there are different levels and not an on/off.A polymorphic table, ex:
permission_user
consisting of something likeentity
,entity_id
,user_id
, and againrole_id
if needed. Here,entity
would be the table/model andentity_id
would be the row's id for that table/model. Now, Lucid doesn't support polymorphic relationships but that doesn't mean you couldn't specifically query for what you need. The downside is, that you can't use foreign keys for theentity_id
since it'll be dynamicA single table with a nullable column per resource, ex:
permission_user
consisting of something likecourse_id
,another_id
,user_id
, and againrole_id
if needed. This is similar to the polymorphic relationship, but you have a specific column per resource needed. Plus here, is you can keep foreign keys. Downside here, is it can be a lot of columns if a lot of resources need to use it.There are many different ways authorization can look beyond these two, but determining what that looks like is the first step.
Populating Permissions
When it comes to populating these permissions, again, it's going to depend on just how granular you need to go. For us in this series, things were simple so our approach was simple. The approach covered here was meant mostly for a single set of roles that then trickle down as needed.
If you're going to be listing courses and each of those courses in the list is going to have varying permissions based on invites/shares, then you might be better off moving the
can
approach to the row level. For example, allowing something likecourse.can.edit
to determine if the authenticated user can edit the course. This could be done using something like model hooks.You could also always reach for a package to help achieve your implementation.
That was a lot, sorry! Hopefully, that helps at least little though.
Please sign in or sign up for free to reply