Plain is headed towards 1.0! Subscribe for development updates →

 1import json
 2
 3from plain.runtime import settings
 4from plain.views import View
 5
 6from .models import Pageview
 7
 8
 9class TrackView(View):
10    def post(self):
11        if getattr(self.request, "impersonator", None):
12            # Don't track page views if we're impersonating a user
13            return 200
14
15        try:
16            data = self.request.data
17        except json.JSONDecodeError:
18            return 400
19
20        try:
21            url = data["url"]
22            title = data["title"]
23            referrer = data["referrer"]
24            timestamp = data["timestamp"]
25        except KeyError:
26            return 400
27
28        if user := getattr(self.request, "user", None):
29            user_id = user.id
30        else:
31            user_id = ""
32
33        if session := getattr(self.request, "session", None):
34            session_instance = session.model_instance
35            session_id = str(session_instance.id) if session_instance else ""
36
37            if settings.PAGEVIEWS_ASSOCIATE_ANONYMOUS_SESSIONS:
38                if not user_id:
39                    if not session_id:
40                        # Make sure we have a key to use
41                        session.create()
42                        session_instance = session.model_instance
43                        session_id = (
44                            str(session_instance.id) if session_instance else ""
45                        )
46
47                    # The user hasn't logged in yet but might later. When they do log in,
48                    # the session key itself will be cycled (session fixation attacks),
49                    # so we'll store the anonymous session id in the data which will be preserved
50                    # when the key cycles, then remove it immediately after.
51                    session["pageviews_anonymous_session_id"] = session_id
52                elif user_id and "pageviews_anonymous_session_id" in session:
53                    # Associate the previously anonymous pageviews with the user
54                    Pageview.query.filter(
55                        user_id="",
56                        session_id=session["pageviews_anonymous_session_id"],
57                    ).update(user_id=user_id)
58
59                    # Remove it so we don't keep trying to associate it
60                    del session["pageviews_anonymous_session_id"]
61        else:
62            session_id = ""
63
64        Pageview.query.create(
65            user_id=user_id,
66            session_id=session_id,
67            url=url,
68            title=title,
69            referrer=referrer,
70            timestamp=timestamp,
71        )
72
73        return 201