Skip to content

Instantly share code, notes, and snippets.

@lcharette
Created December 22, 2016 23:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lcharette/6bc4887c348826119ce56b49a235e50b to your computer and use it in GitHub Desktop.
Save lcharette/6bc4887c348826119ce56b49a235e50b to your computer and use it in GitHub Desktop.
UserFrosting V4 Auth system proposal

Tables

auth_options

  • id
  • slug
  • collection
  • name
  • description

auth_roles

  • id
  • name
  • description
  • collection

auth_roles_data

  • id
  • role_id
  • option_id
  • option_setting (bool)

auth_users

  • user_id
  • collection
  • collection_id
  • role_id

How it works

So let's implement basic can_smell and can_eat permission to the Pizza Collection.

  1. Add permission to auth_options :
id, slug, collection, name, description
...
1, can_smell, Pizza, 'CAN_SMELL_PIZZA, 'CAN_SMELL_PIZZA _DESC'
2, can_eat, Pizza, 'CAN_EAT_PIZZA', 'CAN_EAT_PIZZA_DESC'
  1. Create role in auth_roles
id, name, description, collection
...
1, "Can't eat", "…", Pizza
2, "Can eat", "…", Pizza
  1. Define the roles data in auth_roles_data
id, role_id, option_id, option_setting
...
1, 1, 1, 1 //(Role 1 (Can't eat), can_smell, true)
2, 2, 1, 1 //(Role 2 (Can eat), can_ smell, true)
3, 2, 2, 1 //(Role 2 (Can eat), can_eat, true)

N.B: Since can_eat is not defined for Can't eat role, he can't eat it by default

  1. Assign role to user in auth_users.
user_id, collection, collection_id, role_id
...
2419, Pizza, 1, 1 //(User #2419 Can't eat pizza #1…)
2419, Pizza, 2, 2 //(…but he can eat pizza #2)
...
4321, Pizza, 1, 2 //(User #4321 Can eat pizza #1…)
4321, Pizza, 2, 2 //(… & #2)

And since none of them have a role defined for pizza #3, nobody can smell or eat pizza #3. We could also define a "default" role by adding a default column in the role table.

I'm still not sure how to handle the collection ( Pizza ). I guess it should be linked to something in the php code (like the conditions) and not a db model… (or it would require to specify the whole namespace of the model).

Then, in PHP, where $user is a user object :

$user->auth('can_eat', 2) //return true if the user can eat pizza #2
$user->auth('can_eat') //return true if the user can eat at least one pizza

Or even:

//$auth->(user_id, slug, collection_id)

$auth->get(2419, 'can_eat', 1) //(Return false)
$auth->get(4321, 'can_eat', 1) //(Return true)
$auth->get(4321, 'can_eat') //(Return true, he can eat at least one pizza)

A null collection (and collection_id) would mean this auth_option is global : Assign role to user in auth_users

2419, null, null, 1 //(User #2419 has role admin for example…)
...
$user->auth('adminonly_action_slug') //(Return true since user has role `admin` that allows this permission otpion)

UI

For the UI it's easy to query roles and option per Collection:

Role "Can't eat pizza"

Display all the auth_options for the Pizza collection

Auth_option Setting (True / False button)
Can_smell True
Can_eat False

User 2419 panel:

Display the role for each element in the Pizza collection. (based on the auth_users table where user_id = 2419 and collection = Pizza)

Pizzas Role (Select/dropdown)
Pizza #1 Can't eat
Pizza #2 Can eat
Pizza #3 null (default to can't eat & smell)

Pizza 1 Panel

Display all users role for the Pizza collection with id of 1

Users Role (Select/dropdown)
2419 Can't eat
4321 Can eat
9999 null (default to can't eat & smell)

(This is where group permission could probably help when dealing with thousand of users… while creating a duplicating mess)

Drawback

It doesn't implement the conditions from UFV3, but at the same time it probably won't be necessary anymore... Unless someone wants to implement the "per field" permission. It could still be done, but you would need a auth_options per field.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment