How to use auth policies to exclude some properties on a model when rendering JSON?

26 views Asked by At

I've got some kind of calendar feature in my Laravel app.

Users can have one or more calendars. The owner of a calendar can share it with another user. If an owner shares a calendar with someone, he or she can choose from 4 rules how reading access is arranged. So the owner sets the rules for the person he shares the calendar with. A distinction is made between reading and editing. For now, I'd like to limit my question to authorizing data visibility, the "read" permissions a user receives for a calendar shared with them.

When the owner adds an appointment in his calendar, he can also set the appointment as "private". Below are the rules that the owner can set when it decides to share its calendar with someone. User can be interpreted below as the user who "receives" the right from the owner.

Reading access:

  1. User can only see own added appointments in the calendar shared to him.
  2. User sees added appointments and non-private appointments. The user cannot see the appointments that the owner has set as "private".
  3. User can see their own added appointments, non-private appointments, and only the start and end time of private appointments.
  4. User can see everything in the calendar without restrictions.

I'm trying to use Laravel's Policies and Gates to control visibility. A calendar appointment is an Eloquent model with properties such as id, start date and time, end date and time, title, description, location.

Policies seem to be suitable for almost all authorization logic that can be considered a boolean: is a user allowed to see/do something or not? When a user tries to retrieve the details of any appointment, I can first use a Policy to determine whether the calendar (that relates to the appointment) has been shared at all with the user requesting the data. Then I need to determine what the user can or cannot see in the calendar based on the sharing rule set. The problem mainly lies in limiting the visibility of the details of private appointments when rule 3 is set. In a Policy class for appointments I now have methods like:

- viewFull
- viewRestricted

When I pick up the appointment, I do this:

if(Gate::allows('viewFull', $appointment) { // Tests whether user is allowed to see full details of this specific appointment.
    // Output full Appointment model data (JSON)
}
elseif(Gate::allows('viewRestricted', $appointment)) { // Alternative test whether user can then see restricted data from this specific appointment.
    // Output only some properties of Appointment model.
}
else {
     // Calendar has not been shared with the user, or has no access to this appointment.
}

But this seems cumbersome. Is this the right way?

Also, I've got that Appointment model that contains all the properties. When a user is only allowed to see start and end datetime of an Appointment, I don't know what's the best way to "dump out" some data from the data flow (model -> final output). It feels like I have to set all model properties to null except start and end datetime, but that's sensitive to mistakes if you forget to unset a property on the model.

What is the correct way to arrange this (using Policies or something else)? This type of logic occurs in many applications.

0

There are 0 answers