Search code examples
flaskmongoengineflask-restful

restrict access to certain fields of model


I have a mongoengine model which has some public fields and some fields that I want to hide from, for example, 'user' group. So, what is the smart way to restrict access to some fields?

My stack is Flask-Restful + mongoengine

My idea is to write custom resource serializer and a decorator which should do a restriction. However, the point which is not clear - should this decorator drop some fields from function output or, in opposite, add some fields that suits role?

    @staticmethod
    def serialize_operator(event):
        json_to_decode = {
            "id" : str(event.id), 
            "title" : event.title,
            "description" : event.description,

            "type" : event.type # so I want to hide this field
        }
        return json.loads(json.dumps(json_to_decode))
   @get_auth
   @some_restriction_decorator(user = get_auth())
   def get(self):
       pass

Solution

  • I would suggest defining your serializer in your model class and use fields (from flask_restful) to define it. Then in your controller, you can use the marshal_with decorator (or the marshal function) to serialize the return.

    # Model definition
    from mongoengine import Document, StringField
    from flask_restful import fields
    
    class Article(Document):
        title = StringField()
        description = StringField()
        type = StringField()
    
        public_serializer = {
            'id': fields.String,
            'title': fields.String,
            'description': fields.String
        }
    
    # Controller
    from flask_restful import marshal_with
    
    ...
    @marshal_with(Article.public_serializer)
    def get(self):
        return Article.objects.get(...)
    

    This way only the fields specified in the serializer will be returned.

    Note1: you can define the serializer wherever you want, I just like it to have it in the model.

    Note2: marshal_with handle also list automatically, therefore return list(Article.objects) will also work

    Note3: you can create several serializers and use them differently depending on the situation