Skip to content

Conversation

@yasen-posthog
Copy link
Contributor

Add login/logout activity logging. Add proper impersonation detection during login/logout. Exclude impersonated login/logouts from being shown publicly.

Problem

  • We need these to be tracked

Changes

  • Subscribe to the built-in signals for login and logout and create activity logs from those.
  • Add a special was_impersonated detection in these cases as it's tricky.
  • Hide impersonated login/logouts from normal users, only staff users can see them.

Changelog: (features only) Is this feature complete?

  • Adding login/logout activity logging
… during login/logout. Exclude impersonated login/logouts from being shown publicly.
@yasen-posthog yasen-posthog self-assigned this Oct 31, 2025
@yasen-posthog yasen-posthog requested a review from a-lider October 31, 2025 15:43
Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

9 files reviewed, 2 comments

Edit Code Review Agent Settings | Greptile

Comment on lines 752 to 776
def apply_activity_visibility_restrictions(queryset: QuerySet, user: "User") -> QuerySet:
"""
Apply visibility restrictions to activity log queryset based on user permissions.
"""
exclusion_queries = []
for scope, restrictions in activity_visibility_restrictions.items():
if restrictions.get("requires_staff"):
activities = restrictions.get("activities", [])
exclude_conditions = restrictions.get("exclude_when", {})

# Build the query: scope AND activity IN [...] AND exclude_conditions
query = Q(scope=scope) & Q(activity__in=activities)
for field, value in exclude_conditions.items():
query &= Q(**{field: value})

exclusion_queries.append(query)

# Apply all exclusions with OR logic
if exclusion_queries:
combined_exclusion = exclusion_queries[0]
for q in exclusion_queries[1:]:
combined_exclusion |= q
queryset = queryset.exclude(combined_exclusion)

return queryset
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logic: never checks if user.is_staff is True before excluding the activities

the logic excludes impersonated logins/logouts for ALL users, not just non-staff users. staff users should see these activities but currently cannot

Suggested change
def apply_activity_visibility_restrictions(queryset: QuerySet, user: "User") -> QuerySet:
"""
Apply visibility restrictions to activity log queryset based on user permissions.
"""
exclusion_queries = []
for scope, restrictions in activity_visibility_restrictions.items():
if restrictions.get("requires_staff"):
activities = restrictions.get("activities", [])
exclude_conditions = restrictions.get("exclude_when", {})
# Build the query: scope AND activity IN [...] AND exclude_conditions
query = Q(scope=scope) & Q(activity__in=activities)
for field, value in exclude_conditions.items():
query &= Q(**{field: value})
exclusion_queries.append(query)
# Apply all exclusions with OR logic
if exclusion_queries:
combined_exclusion = exclusion_queries[0]
for q in exclusion_queries[1:]:
combined_exclusion |= q
queryset = queryset.exclude(combined_exclusion)
return queryset
def apply_activity_visibility_restrictions(queryset: QuerySet, user: "User") -> QuerySet:
"""
Apply visibility restrictions to activity log queryset based on user permissions.
"""
exclusion_queries = []
for scope, restrictions in activity_visibility_restrictions.items():
if restrictions.get("requires_staff") and not user.is_staff:
activities = restrictions.get("activities", [])
exclude_conditions = restrictions.get("exclude_when", {})
# Build the query: scope AND activity IN [...] AND exclude_conditions
query = Q(scope=scope) & Q(activity__in=activities)
for field, value in exclude_conditions.items():
query &= Q(**{field: value})
exclusion_queries.append(query)
# Apply all exclusions with OR logic
if exclusion_queries:
combined_exclusion = exclusion_queries[0]
for q in exclusion_queries[1:]:
combined_exclusion |= q
queryset = queryset.exclude(combined_exclusion)
return queryset
Prompt To Fix With AI
This is a comment left during a code review.
Path: posthog/models/activity_logging/activity_log.py
Line: 752:776

Comment:
**logic:** never checks if `user.is_staff` is `True` before excluding the activities

the logic excludes impersonated logins/logouts for ALL users, not just non-staff users. staff users should see these activities but currently cannot

```suggestion
def apply_activity_visibility_restrictions(queryset: QuerySet, user: "User") -> QuerySet:
    """
    Apply visibility restrictions to activity log queryset based on user permissions.
    """
    exclusion_queries = []
    for scope, restrictions in activity_visibility_restrictions.items():
        if restrictions.get("requires_staff") and not user.is_staff:
            activities = restrictions.get("activities", [])
            exclude_conditions = restrictions.get("exclude_when", {})

            # Build the query: scope AND activity IN [...] AND exclude_conditions
            query = Q(scope=scope) & Q(activity__in=activities)
            for field, value in exclude_conditions.items():
                query &= Q(**{field: value})

            exclusion_queries.append(query)

    # Apply all exclusions with OR logic
    if exclusion_queries:
        combined_exclusion = exclusion_queries[0]
        for q in exclusion_queries[1:]:
            combined_exclusion |= q
        queryset = queryset.exclude(combined_exclusion)

    return queryset
```

How can I resolve this? If you propose a fix, please make it concise.
else:
login_method = "sso"
else:
if user.social_auth.exists():
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

style: triggers a database query on every login even if social auth is not being used

consider checking session backend first before querying user.social_auth.exists()

Prompt To Fix With AI
This is a comment left during a code review.
Path: posthog/models/activity_logging/signal_handlers.py
Line: 124:124

Comment:
**style:** triggers a database query on every login even if social auth is not being used

consider checking session backend first before querying `user.social_auth.exists()`

How can I resolve this? If you propose a fix, please make it concise.
@github-actions
Copy link
Contributor

github-actions bot commented Oct 31, 2025

Size Change: 0 B

Total Size: 3.34 MB

ℹ️ View Unchanged
Filename Size
frontend/dist/toolbar.js 3.34 MB

compressed-size-action

@posthog-bot
Copy link
Contributor

📸 UI snapshots have been updated

2 snapshot changes in total. 0 added, 2 modified, 0 deleted:

  • chromium: 0 added, 2 modified, 0 deleted (diff for shard 14)
  • webkit: 0 added, 0 modified, 0 deleted

Triggered by this commit.

👉 Review this PR's diff of snapshots.

@posthog-bot
Copy link
Contributor

📸 UI snapshots have been updated

2 snapshot changes in total. 0 added, 2 modified, 0 deleted:

  • chromium: 0 added, 2 modified, 0 deleted (diff for shard 14)
  • webkit: 0 added, 0 modified, 0 deleted

Triggered by this commit.

👉 Review this PR's diff of snapshots.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

3 participants