GithubHelp home page GithubHelp logo

raekkeri / django-requestlogs Goto Github PK

View Code? Open in Web Editor NEW
60.0 60.0 18.0 76 KB

django-requestlogs is a package providing middleware and other helpers for audit logging.

License: MIT License

Python 100.00%

django-requestlogs's People

Contributors

andrewgy8 avatar chiragkanhasoft avatar gvangool avatar jsoa avatar leogregianin avatar limugob avatar raekkeri avatar ride90 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

django-requestlogs's Issues

Incompatibility with binary files in FileField/ImageField

The default implementation of request serializer that uses JSONEncoder is incompatible with FileField/ImageField that are supported by default in rest_framework(500 UnicodeDecodeError is raised).

In my project I've made a workaround by replacing JsonDumpField as follows:

class JsonDumpField(serializers.Field):
    def to_representation(self, value: QueryDict):
        """
        JSONEncoder doesn't support binary files such as images etc.
        Replace them with string 'File: <filename'
        """
        for val in value.items():
          if isinstance(val[1], InMemoryUploadedFile):
            value.update({ val[0]: f"File: {val[1].name}" })

        return json.dumps(value, cls=JSONEncoder)

The problem can be retrieved with the core functionality of rest_framework, that's why I think it should be solved in the package, not individually in a project.

How to use django-requestlogs with drf @actions???

I have ViewSet with drf @action


class SomeView(BaseViewSet):
    requestlogs_action_names = {
        'list': "Receiving",
        "some_action": "some event has occurred",
    }
    ...

    @action(
        methods=["get"],
        detail=True,
        url_path="some-action",
        url_name="some-action",
    )
    def some_action(self, request, *args, **kwargs):
        some_logic(kwargs)
        return response


I can't get action_name to log

Its my log:

{'action_name': None, ... , ('full_path', '/api/some-action/'), ...}

User IDs that are UUID are converted to Integer in the log

Since the output is for a log (display only), would it make better sense to change "IntegerField" to "CharField" in (storages.py)?

class UserSerializer(serializers.Serializer):
    id = serializers.IntegerField()
    username = serializers.CharField()

Save Log to database

Please,

I'm new in Django and DRF
I want to know ho to logg all my message in a database table
Thank you in advance for your response
DOMGA

Install with Ipware

What do you all think about having a install procedure like:

pip install django-requestlogs[ipware]

which installs the optional dependency.

The project would still maintain the default way of installing pip install django-requestlogs

If desired, this should be as easy as adding

extras_require={"ipware": ["django-ipware"]}

to the setup.py.

Update for Django 4.0

Hey, really making great use of this package. Wanted to ask if this would get updated to support Django 4.
Thanks!

Ignore requests by users

There are users for that I don't need to capture the requests.
Can we create a filter to ignore requests from certain users?

My idea is to create two new configurations:

DEFAULT_SETTINGS = {
     ...
     'IGNORE_USER_FIELD': '',
     'IGNORE_USERS': [],
}

My own configuration would look like this:

REQUESTLOGS = {
     ...
     'IGNORE_USER_FIELD': 'username',
     'IGNORE_USERS': ['username1', 'username2'],
}

or

REQUESTLOGS = {
     ...
     'IGNORE_USER_FIELD': 'email',
     'IGNORE_USERS': ['[email protected]', '[email protected]'],
}

and finalize() method in RequestLogEntry class do:

self.response = self.response_handler(response)

if SETTINGS['IGNORE_USER_FIELD']:
     if (self.user.get(SETTINGS['IGNORE_USER_FIELD'], None) in SETTINGS['IGNORE_USERS']):
         return None

self.store()

@Raekkeri, what do you think about this?

Excluding paths

Hey! Just about to use this on a project of mine.

Is there a way to exclude paths?

For example, I want to exclude logging all /admin/* requests.

TypeError: 'str' object is not callable

I used custom MyEntrySerializer by extending BaseEntrySerializer bcz I was getting issue before (AttributeError: Got AttributeError when attempting to get a value for field user on serializer BaseEntrySerializer.
The serializer field might be named incorrectly and not match any attribute or key on the RequestLogEntry instance.
Original exception text was: 'User' object has no attribute 'username'.), but now getting different issue "TypeError: 'str' object is not callable" , Details are below.
Traceback (most recent call last):
File "/home/algoscale/Desktop/projects/parspec/venv/lib/python3.8/site-packages/django/core/handlers/exception.py", line 34, in inner
response = get_response(request)
File "/home/algoscale/Desktop/projects/parspec/venv/lib/python3.8/site-packages/requestlogs/middleware.py", line 20, in call
get_requestlog_entry(request).finalize(response)
File "/home/algoscale/Desktop/projects/parspec/venv/lib/python3.8/site-packages/requestlogs/entries.py", line 96, in finalize
self.store()
File "/home/algoscale/Desktop/projects/parspec/venv/lib/python3.8/site-packages/requestlogs/entries.py", line 100, in store
storage.store(self)
File "/home/algoscale/Desktop/projects/parspec/venv/lib/python3.8/site-packages/requestlogs/storages.py", line 69, in store
logger.info(self.prepare(entry))
File "/home/algoscale/Desktop/projects/parspec/venv/lib/python3.8/site-packages/requestlogs/storages.py", line 64, in prepare
return self.get_serializer_class()(entry).data
TypeError: 'str' object is not callable

please help to solve this one

drf-yasg compatibility

With swagger enabled, the data property of ResponseHandler gets called when attempting to visit the generated documentation. However in this case, the data is actually a Swagger object, that is derived from dict. A copy of the object is attempted to be made, however with a Swagger object copy() appears to call __init__ of the Swagger class which fails with an error NoneType' object has no attribute '_default_version' ( See https://github.com/axnsan12/drf-yasg/blob/master/src/drf_yasg/openapi.py#L256 )

Pls fix.

django-ipware dependence in README.md

Thank you for your work!

I have noticed, though, that django-ipware package is required for retrieving IP addresses in the logs. It might be helpful to mention that in the document.


There's also a typo here:

The feature is enabled by adding requestlogs.middleware.RequestLogsMiddleware to the MIDDLEWARE setting:

Should actually be

The feature is enabled by adding requestlogs.middleware.RequestIdMiddleware to the MIDDLEWARE setting:

TypeError: Object of type __proxy__ is not JSON serializable

After installing request logs, I started having an error in one of my tests. It was supposed to throw a 400 (BAD REQUEST) error, however, I received a 500 (internal server error). This was my test code:

def test_change_password_with_fake_json(self):
        """Error in password change with invalid JSON."""

        auth_client_with_token(self)
        response = self.client.post(
            API_BASE_USERS_URL + str(self.user.id) + API_BASE_CHANGE_PASSWORD,
            PASSWORD_CHANGE_FAIL,
        )

        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)

The 500 came from the post function. This was the traceback:

Traceback (most recent call last):
    users/tests/test_endpoints.py line 119 in test_change_password_with_fake_json
      PASSWORD_CHANGE_FAIL,
    /usr/local/lib/python3.7/site-packages/rest_framework/test.py line 294 in post
      path, data=data, format=format, content_type=content_type, **extra)
    /usr/local/lib/python3.7/site-packages/rest_framework/test.py line 207 in post
      return self.generic('POST', path, data, content_type, **extra)
    /usr/local/lib/python3.7/site-packages/rest_framework/test.py line 232 in generic
      method, path, data, content_type, secure, **extra)
    /usr/local/lib/python3.7/site-packages/django/test/client.py line 421 in generic
      return self.request(**r)
    /usr/local/lib/python3.7/site-packages/rest_framework/test.py line 283 in request
      return super().request(**kwargs)
    /usr/local/lib/python3.7/site-packages/rest_framework/test.py line 235 in request
      request = super().request(**kwargs)
    /usr/local/lib/python3.7/site-packages/django/test/client.py line 496 in request
      raise exc_value
    /usr/local/lib/python3.7/site-packages/django/core/handlers/exception.py line 34 in inner
      response = get_response(request)
    /home/movisat/.local/lib/python3.7/site-packages/requestlogs/middleware.py line 17 in __call__
      get_requestlog_entry(request).finalize(response)
    /home/movisat/.local/lib/python3.7/site-packages/requestlogs/entries.py line 96 in finalize
      self.store()
    /home/movisat/.local/lib/python3.7/site-packages/requestlogs/entries.py line 100 in store
      storage.store(self)
    /home/movisat/.local/lib/python3.7/site-packages/requestlogs/storages.py line 62 in store
      logger.info(self.prepare(entry))
    /home/movisat/.local/lib/python3.7/site-packages/requestlogs/storages.py line 57 in prepare
      return self.get_serializer_class()(entry).data
    /usr/local/lib/python3.7/site-packages/rest_framework/serializers.py line 562 in data
      ret = super().data
    /usr/local/lib/python3.7/site-packages/rest_framework/serializers.py line 260 in data
      self._data = self.to_representation(self.instance)
    /usr/local/lib/python3.7/site-packages/rest_framework/serializers.py line 529 in to_representation
      ret[field.field_name] = field.to_representation(attribute)
    /usr/local/lib/python3.7/site-packages/rest_framework/serializers.py line 529 in to_representation
      ret[field.field_name] = field.to_representation(attribute)
    /home/movisat/.local/lib/python3.7/site-packages/requestlogs/storages.py line 14 in to_representation
      return json.dumps(value)
    /usr/local/lib/python3.7/json/__init__.py line 231 in dumps
      return _default_encoder.encode(obj)
    /usr/local/lib/python3.7/json/encoder.py line 199 in encode
      chunks = self.iterencode(o, _one_shot=True)
    /usr/local/lib/python3.7/json/encoder.py line 257 in iterencode
      return _iterencode(o, 0)
    /usr/local/lib/python3.7/json/encoder.py line 179 in default
      raise TypeError(f'Object of type {o.__class__.__name__} '
   TypeError: Object of type __proxy__ is not JSON serializable

The error happened in the serializer, in the class JsonDumpField when calling json.dumps(value). I solved it by overriding the serializer, but it could be solved just rewriting the class mentioned before, so I leave you my solution here in case you consider it appropriate to change it in the repo:

class JsonDumpField(serializers.Field):
    def to_representation(self, value):
        try:
            json_obj = json.dumps(value)
        except:
            json_obj = json.dumps(str(value))
        return json_obj

BTW, great job, very useful package!

Include header

Hello,

how to include a header in the request dictionary?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.