You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Let's say that for domain.Training struct if the logged in user is an attendee he cannot see the field notes (it's just an example).
In that amazing article you suggest to put the auth check on repository, using the domain's method CanUserSeeTraining(), great. I can use the same technique with that field only, but now this is a problem if in my repositories I use a code like:
func (rTrainingsFirestoreRepository) GetTraining(
ctx context.Context,
trainingUUIDstring,
user training.User,
) (*training.Training, error) {
firestoreTraining, err:=r.trainingsCollection().Doc(trainingUUID).Get(ctx)
ifstatus.Code(err) ==codes.NotFound {
returnnil, training.NotFoundError{trainingUUID}
}
iferr!=nil {
returnnil, errors.Wrap(err, "unable to get actual docs")
}
tr, err:=r.unmarshalTraining(firestoreTraining)
iferr!=nil {
returnnil, err
}
iferr:=training.CanUserSeeTrainingNotes(user, *tr); err!=nil {
// this is not beautiful this here because we already fetched data from DB that the user cannot see (notes)// return nil, err
}
returntr, nil
}
Plus now we have a problem when we call repository's methods like Relation("Training.Notes") maybe using relational DBs and tools like Gorm: we cannot control what fields are fetched in other repository's methods!
Another way I can think of this is to use the domain's method Notes() (which is also more "secure" as no one can forget to call that method now and it's used each time we unmarshal from DB, whatever repository's method is called):
The second solution also has the drawback of pulling all data from the database, so that doesn't fix it. :)
What I don't like about this approach is that Training suddenly needs to have some notion of the user executing the method. The proper syntax would be:
But not all requests in your system will have a user context. Some may be executed from Pub/Sub messages, some may come from an internal API or CLI tool. As a workaround, you will start manually crafting this "user" passed to the method.
we cannot control what fields are fetched in other repository's methods!
I think it's not an issue, as long as the protected data doesn't leave the repository. The only way around this would be to include your business logic in SQL queries, which doesn't sound great.
So yeah, I think I'd stick to doing this in the repository. Another way could be to expose two repository methods, like:
Thanks for your work on this: it's great!
I have read https://threedots.tech/post/repository-secure-by-design, but I have a doubt about how to fix permissions for individual domain struct fields.
Let's say that for
domain.Training
struct if the logged in user is an attendee he cannot see the fieldnotes
(it's just an example).In that amazing article you suggest to put the auth check on repository, using the domain's method
CanUserSeeTraining()
, great. I can use the same technique with that field only, but now this is a problem if in my repositories I use a code like:Plus now we have a problem when we call repository's methods like
Relation("Training.Notes")
maybe using relational DBs and tools like Gorm: we cannot control what fields are fetched in other repository's methods!Another way I can think of this is to use the domain's method
Notes()
(which is also more "secure" as no one can forget to call that method now and it's used each time we unmarshal from DB, whatever repository's method is called):but I have doubts on this too.
Am I completely wrong to think this way?
What do you think?
The text was updated successfully, but these errors were encountered: