I have an application that allows for multiple users. Each user is completely isolated from each other; this means that everything that's not a user in the database has a user_id
column and only the logged-in user is allowed to view, update, or delete them. In addition, users cannot create rows with someone else's user_id.
Is there a built-in way to solve this with Lumen/Lighthouse? Here's what I've done, and it works, but I'm wondering if I've re-invented the wheel:
user
relationship, like this:public function user(): BelongsTo
{
return $this->belongsTo(User::class);
}
HasOwnerTrait
to these models, with the following contents:public static function boot()
{
parent::boot();
static::creating(function (Model $model) {
$model->user_id = Auth::user()->id;
});
static::saving(function (Model $model) {
if ($model->user_id !== Auth::user()->id) {
$exception = new ModelNotFoundException();
$exception->setModel(self::class, $model->id);
throw $exception;
}
});
static::deleting(function (Model $model) {
if ($model->user_id !== Auth::user()->id) {
$exception = new ModelNotFoundException();
$exception->setModel(self::class, $model->id);
throw $exception;
}
});
}
public function scopeIsOwner($query)
{
return $query->where('user_id', Auth::user()->id);
}
type Query {
recipes: [Recipe!]! @all(scopes: ["isOwner"])
}
type Mutation {
createRecipe(input: CreateRecipeInput! @spread): Recipe @create
updateRecipe(id: ID!, input: UpdateRecipeInput! @spread): Recipe @update
deleteRecipe(id: ID!): Recipe @delete
}
Again, this is working, but does it need to be ad hoc like this, or is there a better way?
I think your solution is fine, it saves writing a whole bunch of boilerplate. A few minor suggestions:
You can make your trait into a bootable trait that is automatically called by the framework by renaming the boot
method to bootHasOwnerTrait
.
Maybe consider making the isOwner
scope active by default. In Laravel, this is confusingly called a global scope. That allows you to omit naming the scope explicitly, although you can still omit it if you have some queries where it should not apply, e.g. statistics.