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

Commit 2d74a8c

Browse files
authored
Add mau_appservice_trial_days config (#12619)
* Add mau_appservice_trial_days * Add a test * Tweaks * changelog * Ensure we sync after the delay * Fix types * Add config statement * Fix test * Reinstate logging that got removed * Fix feature name
1 parent 7fbf424 commit 2d74a8c

File tree

6 files changed

+110
-2
lines changed

6 files changed

+110
-2
lines changed

changelog.d/12619.feature

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Add new `mau_appservice_trial_days` configuration option to specify a different trial period for users registered via an appservice.

docs/sample_config.yaml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,11 @@ manhole_settings:
407407
# sign up in a short space of time never to return after their initial
408408
# session.
409409
#
410+
# The option `mau_appservice_trial_days` is similar to `mau_trial_days`, but
411+
# applies a different trial number if the user was registered by an appservice.
412+
# A value of 0 means no trial days are applied. Appservices not listed in this
413+
# dictionary use the value of `mau_trial_days` instead.
414+
#
410415
# 'mau_limit_alerting' is a means of limiting client side alerting
411416
# should the mau limit be reached. This is useful for small instances
412417
# where the admin has 5 mau seats (say) for 5 specific people and no
@@ -417,6 +422,8 @@ manhole_settings:
417422
#max_mau_value: 50
418423
#mau_trial_days: 2
419424
#mau_limit_alerting: false
425+
#mau_appservice_trial_days:
426+
# "appservice-id": 1
420427

421428
# If enabled, the metrics for the number of monthly active users will
422429
# be populated, however no one will be limited. If limit_usage_by_mau

docs/usage/configuration/config_documentation.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -627,6 +627,20 @@ Example configuration:
627627
mau_trial_days: 5
628628
```
629629
---
630+
Config option: `mau_appservice_trial_days`
631+
632+
The option `mau_appservice_trial_days` is similar to `mau_trial_days`, but applies a different
633+
trial number if the user was registered by an appservice. A value
634+
of 0 means no trial days are applied. Appservices not listed in this dictionary
635+
use the value of `mau_trial_days` instead.
636+
637+
Example configuration:
638+
```yaml
639+
mau_appservice_trial_days:
640+
my_appservice_id: 3
641+
another_appservice_id: 6
642+
```
643+
---
630644
Config option: `mau_limit_alerting`
631645

632646
The option `mau_limit_alerting` is a means of limiting client-side alerting

synapse/config/server.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,7 @@ def read_config(self, config: JsonDict, **kwargs: Any) -> None:
413413
)
414414

415415
self.mau_trial_days = config.get("mau_trial_days", 0)
416+
self.mau_appservice_trial_days = config.get("mau_appservice_trial_days", {})
416417
self.mau_limit_alerting = config.get("mau_limit_alerting", True)
417418

418419
# How long to keep redacted events in the database in unredacted form
@@ -1105,6 +1106,11 @@ def generate_config_section(
11051106
# sign up in a short space of time never to return after their initial
11061107
# session.
11071108
#
1109+
# The option `mau_appservice_trial_days` is similar to `mau_trial_days`, but
1110+
# applies a different trial number if the user was registered by an appservice.
1111+
# A value of 0 means no trial days are applied. Appservices not listed in this
1112+
# dictionary use the value of `mau_trial_days` instead.
1113+
#
11081114
# 'mau_limit_alerting' is a means of limiting client side alerting
11091115
# should the mau limit be reached. This is useful for small instances
11101116
# where the admin has 5 mau seats (say) for 5 specific people and no
@@ -1115,6 +1121,8 @@ def generate_config_section(
11151121
#max_mau_value: 50
11161122
#mau_trial_days: 2
11171123
#mau_limit_alerting: false
1124+
#mau_appservice_trial_days:
1125+
# "appservice-id": 1
11181126
11191127
# If enabled, the metrics for the number of monthly active users will
11201128
# be populated, however no one will be limited. If limit_usage_by_mau

synapse/storage/databases/main/registration.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,8 @@ async def get_userinfo_by_id(self, user_id: str) -> Optional[UserInfo]:
215215

216216
async def is_trial_user(self, user_id: str) -> bool:
217217
"""Checks if user is in the "trial" period, i.e. within the first
218-
N days of registration defined by `mau_trial_days` config
218+
N days of registration defined by `mau_trial_days` config or the
219+
`mau_appservice_trial_days` config.
219220
220221
Args:
221222
user_id: The user to check for trial status.
@@ -226,7 +227,10 @@ async def is_trial_user(self, user_id: str) -> bool:
226227
return False
227228

228229
now = self._clock.time_msec()
229-
trial_duration_ms = self.config.server.mau_trial_days * 24 * 60 * 60 * 1000
230+
days = self.config.server.mau_appservice_trial_days.get(
231+
info["appservice_id"], self.config.server.mau_trial_days
232+
)
233+
trial_duration_ms = days * 24 * 60 * 60 * 1000
230234
is_trial = (now - info["creation_ts"] * 1000) < trial_duration_ms
231235
return is_trial
232236

tests/test_mau.py

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414

1515
"""Tests REST events for /rooms paths."""
1616

17+
from typing import List
18+
1719
from synapse.api.constants import APP_SERVICE_REGISTRATION_TYPE, LoginType
1820
from synapse.api.errors import Codes, HttpResponseException, SynapseError
1921
from synapse.appservice import ApplicationService
@@ -229,6 +231,78 @@ def test_tracked_but_not_limited(self):
229231
self.reactor.advance(100)
230232
self.assertEqual(2, self.successResultOf(count))
231233

234+
@override_config(
235+
{
236+
"mau_trial_days": 3,
237+
"mau_appservice_trial_days": {"SomeASID": 1, "AnotherASID": 2},
238+
}
239+
)
240+
def test_as_trial_days(self):
241+
user_tokens: List[str] = []
242+
243+
def advance_time_and_sync():
244+
self.reactor.advance(24 * 60 * 61)
245+
for token in user_tokens:
246+
self.do_sync_for_user(token)
247+
248+
# Cheekily add an application service that we use to register a new user
249+
# with.
250+
as_token_1 = "foobartoken1"
251+
self.store.services_cache.append(
252+
ApplicationService(
253+
token=as_token_1,
254+
hostname=self.hs.hostname,
255+
id="SomeASID",
256+
sender="@as_sender_1:test",
257+
namespaces={"users": [{"regex": "@as_1.*", "exclusive": True}]},
258+
)
259+
)
260+
261+
as_token_2 = "foobartoken2"
262+
self.store.services_cache.append(
263+
ApplicationService(
264+
token=as_token_2,
265+
hostname=self.hs.hostname,
266+
id="AnotherASID",
267+
sender="@as_sender_2:test",
268+
namespaces={"users": [{"regex": "@as_2.*", "exclusive": True}]},
269+
)
270+
)
271+
272+
user_tokens.append(self.create_user("kermit1"))
273+
user_tokens.append(self.create_user("kermit2"))
274+
user_tokens.append(
275+
self.create_user("as_1kermit3", token=as_token_1, appservice=True)
276+
)
277+
user_tokens.append(
278+
self.create_user("as_2kermit4", token=as_token_2, appservice=True)
279+
)
280+
281+
# Advance time by 1 day to include the first appservice
282+
advance_time_and_sync()
283+
self.assertEqual(
284+
self.get_success(self.store.get_monthly_active_count_by_service()),
285+
{"SomeASID": 1},
286+
)
287+
288+
# Advance time by 1 day to include the next appservice
289+
advance_time_and_sync()
290+
self.assertEqual(
291+
self.get_success(self.store.get_monthly_active_count_by_service()),
292+
{"SomeASID": 1, "AnotherASID": 1},
293+
)
294+
295+
# Advance time by 1 day to include the native users
296+
advance_time_and_sync()
297+
self.assertEqual(
298+
self.get_success(self.store.get_monthly_active_count_by_service()),
299+
{
300+
"SomeASID": 1,
301+
"AnotherASID": 1,
302+
"native": 2,
303+
},
304+
)
305+
232306
def create_user(self, localpart, token=None, appservice=False):
233307
request_data = {
234308
"username": localpart,

0 commit comments

Comments
 (0)