Learn more about our current job openings and benefits of working at FSL.
Detailed reviews and feedback from past and current clients.
Get to know the Management Team behind FullStack Labs.
Our step-by-step process for designing and developing new applications.
Writings from our team on technology, design, and business.
Get answers to the questions most frequently asked by new clients.
Learn about our company culture and defining principles.
A high level overview of FullStack Labs, who we are, and what we do.
A JavaScript framework that allows rapid development of native Android and IOS apps.
A JavaScript framework maintained by Facebook that's ideal for building complex, modern user interfaces within single page web apps.
A server side programming language known for its ease of use and speed of development.
A lightweight and efficient backend javascript framework for web apps.
An interpreted high-level programming language great for general purpose programming.
A JavaScript framework maintained by Google that addresses many of the challenges encountered when building single-page apps.
A JavaScript framework that allows developers to build large, complex, scalable single-page web applications.
A progressive JavaScript framework known for its approachability, versatility, and performance.
A progressive JavaScript framework known for its approachability, versatility, and performance.
A progressive JavaScript framework known for its approachability, versatility, and performance.
A progressive JavaScript framework known for its approachability, versatility, and performance.
A progressive JavaScript framework known for its approachability, versatility, and performance.
A progressive JavaScript framework known for its approachability, versatility, and performance.
A progressive JavaScript framework known for its approachability, versatility, and performance.
View a sampling of our work implemented using a variety of our favorite technologies.
View examples of the process we use to build custom software solutions for our clients.
View projects implemented using this javascript framework ideal for building complex, modern user interfaces within single page web apps.
View projects implemented using this framework that allows rapid development of native Android and IOS apps.
View projects implemented using this backend javascript framework for web apps.
View projects implemented using this high-level programming language great for general purpose programming.
View projects implemented using this server side programming language known for its ease of use and speed of development.
We have vast experience crafting healthcare software development solutions, including UI/UX Design, Application Development, Legacy Healthcare Systems, and Team Augmentation. Our development services help the healthcare industry by enhancing accessibility, productivity, portability, and scalability.
We offer a range of custom software development solutions for education companies of all sizes. We're experts in Education Software Development and specialists in enhancing the learning experience across web, mobile, and conversational UI.
We're experts in developing Custom Software Solutions for the Logistics Industry. Our work offered a whole new and more efficient way for Logistics companies to manage their crucial operations.
We partner with various construction industry organizations to build custom software development solutions. Our Construction Software Development Services allow construction companies to manage projects, resources, and documentation.
We have vast experience crafting healthcare software development solutions, including UI/UX Design, Application Development, Legacy Healthcare Systems, and Team Augmentation. Our development services help the healthcare industry by enhancing accessibility, productivity, portability, and scalability.
We offer a range of custom software development solutions for education companies of all sizes. We're experts in Education Software Development and specialists in enhancing the learning experience across web, mobile, and conversational UI.
We're experts in developing Custom Software Solutions for the Logistics Industry. Our work offered a whole new and more efficient way for Logistics companies to manage their crucial operations.
We partner with various construction industry organizations to build custom software development solutions. Our Construction Software Development Services allow construction companies to manage projects, resources, and documentation.
Learn more about our current job openings and benefits of working at FSL.
Detailed reviews and feedback from past and current clients.
Get to know the Management Team behind FullStack Labs.
Our step-by-step process for designing and developing new applications.
Writings from our team on technology, design, and business.
Get answers to the questions most frequently asked by new clients.
Learn about our company culture and defining principles.
A high level overview of FullStack Labs, who we are, and what we do.
A JavaScript framework that allows rapid development of native Android and IOS apps.
A JavaScript framework maintained by Facebook that's ideal for building complex, modern user interfaces within single page web apps.
A server side programming language known for its ease of use and speed of development.
A lightweight and efficient backend javascript framework for web apps.
An interpreted high-level programming language great for general purpose programming.
A JavaScript framework maintained by Google that addresses many of the challenges encountered when building single-page apps.
A JavaScript framework that allows developers to build large, complex, scalable single-page web applications.
A progressive JavaScript framework known for its approachability, versatility, and performance.
A dynamic programming language used in all sorts of web and mobile applications.
A cross-platform programming language designed to run robust applications on any device.
A UI toolkit used to build natively compiled applications from a single codebase.
A functional programming language that’s ideal for scalability, maintainability, and reliability.
A Customer Relationship Management (CRM) platform that seamlessly integrates with your business operations.
A high-performance programming language that makes it easy to build simple, reliable, and efficient software.
View a sampling of our work implemented using a variety of our favorite technologies.
View examples of the process we use to build custom software solutions for our clients.
View projects implemented using this javascript framework ideal for building complex, modern user interfaces within single page web apps.
View projects implemented using this framework that allows rapid development of native Android and IOS apps.
View projects implemented using this backend javascript framework for web apps.
View projects implemented using this high-level programming language great for general purpose programming.
View projects implemented using this server side programming language known for its ease of use and speed of development.
I was recently tasked with implementing role-based user authorization in a client's application and after some research, decided to try a new library that I had never worked with before called CASL.
I enjoyed working with it and would like to show you just how easy it is to set up and start using it in your projects.
https://github.com/stalniy/casl
CASL (pronounced /ˈkæsəl/, like castle) is an isomorphic authorization JavaScript library which restricts what resources a given user is allowed to access. All permissions are defined in a single location (the Ability class) and not duplicated across UI components, API services, and database queries.
CASL, because of its isomorphic nature, can be used together with any data layer, any HTTP framework, and even any frontend framework.
For this example, we'll be defining two roles for our users, Admin and Pleb.
An Admin user will be able to "manage" posts. This means that they can perform any action on the given resource.
A Pleb will be able to read and update posts, but not create or delete them.
First, we define a function to create and return an ability for each role.
-- CODE language-javascript keep-markup --
/* roles.js */
import { AbilityBuilder, Ability } from '@casl/ability'
exportconst PERMISSIONS = {
MANAGE: 'manage',
CREATE: 'create',
READ: 'read',
UPDATE: 'update',
DELETE: 'delete'
}
exportconst MODEL_NAMES = { POST: 'Post' }
exportfunctiondefineAbilitiesForAdmin() {
const { rules, can } = AbilityBuilder.extract()
can(PERMISSIONS.MANAGE, MODEL_NAMES.POST)
returnnew Ability(rules)
}
exportfunctiondefineAbilitiesForPleb() {
const { rules, can, cannot } = AbilityBuilder.extract()
can(PERMISSIONS.MANAGE, MODEL_NAMES.POST) /* start with full permissions */
cannot(PERMISSIONS.CREATE, MODEL_NAMES.POST)
.because('Only Admins can create Posts')
cannot(PERMISSIONS.DELETE, MODEL_NAMES.POST)
.because('Only Admins can delete Posts')
returnnew Ability(rules)
}
We could pass some data to our functions to conditionally add/remove abilities for the role but let's keep it simple for now.
Next, let's add a function to fetch the abilities for a user based upon their role.
We'll define a default role with no permissions in case the user doesn't have a role set yet.
-- CODE language-javascript keep-markup --
/* utils.js */
import { AbilityBuilder, Ability } from '@casl/ability'
import {
defineAbilitiesForAdmin,
defineAbilitiesForPleb}
from './roles'
const USER_ROLES = {
ADMIN: 1,
PLEB: 2
}
const DEFAULT_ABILITIES = new Ability() //defaults to no permissions
exportfunctiongetRoleAbilityForUser({ user = {} }) {
let ability
switch (user.role) {
case USER_ROLES.ADMIN:
ability = defineAbilitiesForAdmin()
break
case USER_ROLES.PLEB:
ability = defineAbilitiesForPleb()
break
default:
ability = DEFAULT_ABILITIES
break
}
return ability
}
Great! Now we have both our Admin and Pleb roles defined and we have a function to fetch the abilities for a given user.
Let's put them to use by checking if the user has permission to create a post in a controller action.
CASL has a nice ForbiddenError helper that we can use to throw an error with a helpful message if the user doesn't have the correct permissions.
-- CODE language-javascript keep-markup --
/* PostController.js */
import { ForbiddenError } from '@casl/ability'
import { PERMISSIONS, MODEL_NAMES } from './roles'
import { getRoleAbilityForUser } from './utils'
classPostController {
async createPost(req, res) {
const { user = {} } = req
try {
const ability = getRoleAbilityForUser({ user })
ForbiddenError.from(ability)
.throwUnlessCan(PERMISSIONS.CREATE, MODEL_NAMES.POST)
//create the post!
} catch (error) {
console.log(error.message) /* "Only Admins can create Posts" */
}
}
}
exportdefault PostController
Finally, let's add a controller action to fetch the ability for the current user so we can check their permissions client-side.
CASL has some helper functions to pack/unpack the rules for the abilities to reduce the size for storage in a jwt token. We'll skip the token part for now but keep the optimization.
-- CODE language-javascript keep-markup --
/* controller.js */
import { packRules } from '@casl/ability/extra'
import { getRoleAbilityForUser } from './utils'
classUserController {
getUserRoleAbility(req, res) {
const { user = {} } = req
try {
const ability = getRoleAbilityForUser({ user })
const packedRules = packRules(ability.rules)
return res.status(200).send(packedRules)
} catch (error) {
/* handle the error */
res.status(501).send(error)
}
}
}
exportdefault UserController
We'll use React in this example but we can just as easily use CASL by itself as we did on the server.
-- CODE language-javascript keep-markup --
import { Ability } from '@casl/ability'
const ability = new Ability() /* defaults to no permissions */
ability.can('create', 'Post') /* returns false */
Notice that we are using the same @casl/ability packages on the client as we did on the server!
There are also complementary libraries for other major frontend frameworks which makes integration of CASL super easy in your application.
First, let's add a hook to define and update our users' abilities.
-- CODE language-javascript keep-markup --
/* useAbility.js */
import { Ability } from '@casl/ability'
import { unpackRules } from '@casl/ability/extra'
import { UserApi } from './api'
const userAbility = new Ability()
exportfunctionuseAbility() {
asyncfunctionfetchUserAbility() {
try {
const { data: packedRules } = await UserApi.fetchAbility()
userAbility.update(unpackRules(packedRules))
} catch (error) {
/* handle the error */
}
return userAbility
}
return {
fetchUserAbility,
userAbility
}
}
Now, let's take a look at how to conditionally render a button if the user has the correct permissions to create a new post.
-- CODE language-javascript keep-markup --
/* CreatePostButton.js */
import { Can } from '@casl/react'
import { useAbility, usePost } from './hooks'
functionCreatePostButton() {
const { fetchUserAbility, userAbility } = useAbility()
const { createPost } = usePost()
const [fetched, setFetched] = useState(false)
useEffect(() => {
if (!fetched) {
fetchUserAbility()
setFetched(true)
}
}, [fetched, setFetched, fetchUserAbility])
/* shown for admins, hidden by default and for plebs */
return ( <
Can I="create" a="Post" ability={userAbility}>
<button onclick="{createPost}">Create Post</button>
)
}
That's it! Simple and very non-intimidating, right?
Check out the CASL documentation for a deeper dive.
https://github.com/stalniy/casl
Thanks for reading!
Using techniques like what is listed above, we have had the opportunity to address our clients’ concerns and they love it! If you are interested in joining our team, please visit our Careers page.
---
At FullStack Labs, we are consistently asked for ways to speed up time-to-market and improve project maintainability. We pride ourselves on our ability to push the capabilities of these cutting-edge libraries. Interested in learning more about speeding up development time on your next form project, or improving an existing codebase with forms? Contact us.
We’d love to learn more about your project.
Engagements start at $75,000.