Skip to content
This repository has been archived by the owner on Apr 26, 2024. It is now read-only.

Allow tracking puppeted users for MAU #11561

Merged
merged 6 commits into from
Jan 12, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.d/11561.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add config flag `mau_track_puppeted_users` to allow tracking puppeted users in terms of monthly active users.
jaywink marked this conversation as resolved.
Show resolved Hide resolved
5 changes: 5 additions & 0 deletions docs/sample_config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,11 @@ manhole_settings:
# - medium: 'email'
# address: 'reserved_user@example.com'

# If enabled, puppeted users can also be tracked. By default when
# puppeting another user, the user who has created the access token
# for puppeting is tracked. If this is enabled, both requests are tracked.
#mau_track_puppeted_users: false
jaywink marked this conversation as resolved.
Show resolved Hide resolved

# Used by phonehome stats to group together related servers.
#server_context: context

Expand Down
13 changes: 13 additions & 0 deletions synapse/api/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ def __init__(self, hs: "HomeServer"):
self._track_appservice_user_ips = hs.config.appservice.track_appservice_user_ips
self._macaroon_secret_key = hs.config.key.macaroon_secret_key
self._force_tracing_for_users = hs.config.tracing.force_tracing_for_users
self._mau_track_puppeted_users = hs.config.server.mau_track_puppeted_users

async def check_user_in_room(
self,
Expand Down Expand Up @@ -208,6 +209,18 @@ async def get_user_by_req(
user_agent=user_agent,
device_id=device_id,
)
# Track also the puppeted user client IP if enabled and the user is puppeting
if (
user_info.user_id != user_info.token_owner
and self._mau_track_puppeted_users
):
await self.store.insert_client_ip(
user_id=user_info.user_id,
access_token=access_token,
ip=ip_addr,
user_agent=user_agent,
device_id=device_id,
)
squahtx marked this conversation as resolved.
Show resolved Hide resolved

if is_guest and not allow_guest:
raise AuthError(
Expand Down
6 changes: 6 additions & 0 deletions synapse/config/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,7 @@ def read_config(self, config, **kwargs):

self.mau_trial_days = config.get("mau_trial_days", 0)
self.mau_limit_alerting = config.get("mau_limit_alerting", True)
self.mau_track_puppeted_users = config.get("mau_track_puppeted_users", False)

# How long to keep redacted events in the database in unredacted form
# before redacting them.
Expand Down Expand Up @@ -1128,6 +1129,11 @@ def generate_config_section(
# - medium: 'email'
# address: 'reserved_user@example.com'

# If enabled, puppeted users can also be tracked. By default when
# puppeting another user, the user who has created the access token
# for puppeting is tracked. If this is enabled, both requests are tracked.
#mau_track_puppeted_users: false

# Used by phonehome stats to group together related servers.
#server_context: context

Expand Down
33 changes: 33 additions & 0 deletions tests/api/test_auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,39 @@ def test_get_user_by_req_appservice_valid_token_bad_user_id(self):
request.requestHeaders.getRawHeaders = mock_getRawHeaders()
self.get_failure(self.auth.get_user_by_req(request), AuthError)

def test_get_user_by_req__puppeted_token__not_tracking_puppeted_mau(self):
self.store.get_user_by_access_token = simple_async_mock(
TokenLookupResult(
user_id="@baldrick:matrix.org",
device_id="device",
token_owner="@admin:matrix.org",
)
)
self.store.insert_client_ip = simple_async_mock(None)
request = Mock(args={})
request.getClientIP.return_value = "127.0.0.1"
request.args[b"access_token"] = [self.test_token]
request.requestHeaders.getRawHeaders = mock_getRawHeaders()
self.get_success(self.auth.get_user_by_req(request))
self.store.insert_client_ip.assert_called_once()

def test_get_user_by_req__puppeted_token__tracking_puppeted_mau(self):
self.auth._mau_track_puppeted_users = True
self.store.get_user_by_access_token = simple_async_mock(
TokenLookupResult(
user_id="@baldrick:matrix.org",
device_id="device",
token_owner="@admin:matrix.org",
)
)
self.store.insert_client_ip = simple_async_mock(None)
request = Mock(args={})
request.getClientIP.return_value = "127.0.0.1"
request.args[b"access_token"] = [self.test_token]
request.requestHeaders.getRawHeaders = mock_getRawHeaders()
self.get_success(self.auth.get_user_by_req(request))
self.assertEquals(self.store.insert_client_ip.call_count, 2)

def test_get_user_from_macaroon(self):
self.store.get_user_by_access_token = simple_async_mock(
TokenLookupResult(user_id="@baldrick:matrix.org", device_id="device")
Expand Down