QueryAuth - A Type-Safe permissions system

QueryAuth is a lightweight, type-safe permissions module for Roblox.


Get it on GitHub
Get it on Wally


QueryAuth aims to solve a problem in multiple genres of Roblox games, permissions. Often, when making a game that needs any form of permission checks to see if a player is able to do a certain action, you’ll end up making complex, hard-coded branches of if-statements. With QueryAuth it’s as simple as running one of the various auth conditions, and passing in the player. Other current alternatives are NOT type-safe, and typically use strings to pass in arguments, which is an extremely bad practice. Because all Auth Conditions are just lambdas, you can pass in any lambda that takes in a player.


Below you can see an example of using QueryAuth
local condition = QueryAuth.one { -- ONLY returns true if one or more conditions are true QueryAuth.UserId({123456}), QueryAuth.Team("Enemy"), QueryAuth.all { -- ONLY returns true if ALL conditions are true. You can nest these because they return Lambdas. QueryAuth.UserId({654321}), QueryAuth.Team("Heroes") }, function(plr: Player) -- Because conditions return a Lambda, you can just put a function in that returns a boolean! return RunService:IsStudio() end } print(condition(player)) -- Conditions are just functions, so you run them using parentheses. 

Let’s break this down into smaller chunks.

In QueryAuth, there’s currently 3 ways of making an Auth Condition.

  • QueryAuth.one(conditions)
  • QueryAuth.all(conditions)
  • QueryAuth.has(amount, conditions)

All auth conditions are purely just functions that take in a player, and return a boolean. This means all of these functions just return a function that you can call at any time! You can find out how to use each of these built-in functions below.


QueryAuth.one()

Takes in a list of other conditions, and returns true if only ONE of them are true.

Basic example:

local condition = QueryAuth.one { QueryAuth.Team {"Class-D"}, QueryAuth.UserId {123456} } -- Will print true if the player is on the Class-D team, or if their ID is 123456. print(condition(player)) 
QueryAuth.all()

Takes in a list of other conditions, and returns true if only ALL of them are true.

Basic example:

local condition = QueryAuth.all { QueryAuth.Team {"Class-D"}, QueryAuth.UserId {123456} } -- Will print true if the player is on the Class-D team, AND their ID is 123456. print(condition(player)) 
QueryAuth.has()

Takes in a list of other conditions, and returns true if at least amount is true.

Basic example:

local condition = QueryAuth.has 2 { QueryAuth.Team {"Class-D"}, QueryAuth.UserId {123456}, function(plr: Player) return RunService:IsStudio() end } -- Will print true if 2 of the conditions are true. print(condition(player)) 

QueryAuth also comes with a few built-in functions that can be used inside of your conditions. Currently, the only ones supported are

  • QueryAuth.Team()
  • QueryAuth.UserId()

More will be added in the future, but since these just return a function, you can just make your own function that returns another function. Here’s an example of how Team works:

Example
return function(values: {string}?)	return function(player: Player): boolean return values == nil or (player.Team ~= nil and table.find(values, player.Team.Name) ~= nil) end end 

Hopefully you can see the serious potential this can have in many genres of games, and help support the project! This is pretty much my first open-source library I’ve released to the public so let me know if you have any suggestions / feedback. Thank you!

10 Likes

Neat. Though, while some devs won’t be bothered with making if branches for permissions, this seems simple enough to be educational. Nice.

1 Like

If statements work for a lot of people, but once you start needing logic for hundreds of doors, or hundreds of items it can become cluttered, instead you can store permission groups in modulescripts somewhere & just use query auth to make it very simple