Starchart: Matching Database With SAML Claims
cychu42
Posted on March 11, 2023
Task
What I did this week was matching User
table of database in Starchart project with what useful information SAML would return about users when users log in.
This meant adding group
column in User
table in database, given it's one of the claims. group
claim is used as role assignment, such as user being part of student group, which has specific access attached to the group.
This project uses Prisma to interact with the database.
There were 3 things I needed to do:
- Edit the schema file (
prisma\schema.prisma
). - Edit the file (
prisma\seed.ts
) for seeding to make sure these seeded users have groups. - Chang how relevant functions interact with the database, so a function that make Prisma API call to create a user would need to be changed for the addition of
group
. When changing a function definition, one needs to remember to change how the function is used in other area of your code. For example, I changed the parameter ofcreateUser()
to allow argument forgroup
, so I must change how the function is used elsewhere in the project too. -
Cover new use cases for the column. This meant I added 3 functions to check whether a user belongs to one of 3 groups. The functions
isStudent()
,isFaculty()
, andisAdmin()
acceptusername
as parameter. They would returntrue
if they have the role/group,false
if not. The code look something like this:
export async function isFaculty(username: PrismaUser['username']) { const { group } = await prisma.user.findUniqueOrThrow({ where: { username } }); // The group will have -dev in it on staging but not on prod return /mycustomdomain(-dev)?-faculty/.test(group); }
async
marks this function as asynchronous, since it needs to interact with the database andawait
a response.The
group
value will be returned by the Prisma function after it fetches the user, by using the primary keyusername
. Notice typescript syntax is used to limit the type ofusername
according to PrismaUser
model'susername
column type.]
findUniqueOrThrow()
will throw error if nothing is found, as the function name suggests. You can see the documentation here.After
group
is returned, a regular expression is used and test against thegroup
value. If there's a match, it will returntrue
, orfalse
in the case of no match. This looks for anymycustomdomain-faculty
ormycustomdomain-dev-faculty
ingroup
. Consider other adjustment to codes relating to
User
. There was no need for additional adjustment for this, but I could easily needed to do so. For example, if I changed a column name, I would need to change other references to the name in the project.
Also, I merged firstName
and lastName
columns into one displayName
column, given that's what SAML gives back. The same ideas for such changes in database schema apply: edit the schema file, edit the seeding file, change/add relevant functions, and other relevant code adjustment. In this case, no new function was added.
Change Log Of The PR:
- Add group in
User
model as String inprisma\schema.prisma
- Add examples in
prisma\seed.ts
- Modify
createUser()
inapp\models\user.server.ts
accordingly - Add
isStudent()
,isFaculty()
, andisAdmin()
inapp\models\user.server.ts
. - Combine
firstName
andlastName
intodisplayName
- Modify arguments of
createUser()
inapp\routes\login\callback.tsx
isStudent()
, isFaculty()
, and isAdmin()
accept username
as parameter. They would return true
if they have the role/group, false
if not.
Posted on March 11, 2023
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.