Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.
 
 
 
 
 
 

191 rinda
5.8 KiB

  1. # Copyright 2021 The Matrix.org Foundation C.I.C.
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License");
  4. # you may not use this file except in compliance with the License.
  5. # You may obtain a copy of the License at
  6. #
  7. # http://www.apache.org/licenses/LICENSE-2.0
  8. #
  9. # Unless required by applicable law or agreed to in writing, software
  10. # distributed under the License is distributed on an "AS IS" BASIS,
  11. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. # See the License for the specific language governing permissions and
  13. # limitations under the License.
  14. import argparse
  15. import sys
  16. import time
  17. from datetime import datetime
  18. from typing import List
  19. import attr
  20. from synapse.config._base import (
  21. Config,
  22. RootConfig,
  23. find_config_files,
  24. read_config_files,
  25. )
  26. from synapse.config.database import DatabaseConfig
  27. from synapse.storage.database import DatabasePool, LoggingTransaction, make_conn
  28. from synapse.storage.engines import create_engine
  29. class ReviewConfig(RootConfig):
  30. "A config class that just pulls out the database config"
  31. config_classes = [DatabaseConfig]
  32. @attr.s(auto_attribs=True)
  33. class UserInfo:
  34. user_id: str
  35. creation_ts: int
  36. emails: List[str] = attr.Factory(list)
  37. private_rooms: List[str] = attr.Factory(list)
  38. public_rooms: List[str] = attr.Factory(list)
  39. ips: List[str] = attr.Factory(list)
  40. def get_recent_users(
  41. txn: LoggingTransaction, since_ms: int, exclude_app_service: bool
  42. ) -> List[UserInfo]:
  43. """Fetches recently registered users and some info on them."""
  44. sql = """
  45. SELECT name, creation_ts FROM users
  46. WHERE
  47. ? <= creation_ts
  48. AND deactivated = 0
  49. """
  50. if exclude_app_service:
  51. sql += " AND appservice_id IS NULL"
  52. txn.execute(sql, (since_ms / 1000,))
  53. user_infos = [UserInfo(user_id, creation_ts) for user_id, creation_ts in txn]
  54. for user_info in user_infos:
  55. user_info.emails = DatabasePool.simple_select_onecol_txn(
  56. txn,
  57. table="user_threepids",
  58. keyvalues={"user_id": user_info.user_id, "medium": "email"},
  59. retcol="address",
  60. )
  61. sql = """
  62. SELECT room_id, canonical_alias, name, join_rules
  63. FROM local_current_membership
  64. INNER JOIN room_stats_state USING (room_id)
  65. WHERE user_id = ? AND membership = 'join'
  66. """
  67. txn.execute(sql, (user_info.user_id,))
  68. for room_id, canonical_alias, name, join_rules in txn:
  69. if join_rules == "public":
  70. user_info.public_rooms.append(canonical_alias or name or room_id)
  71. else:
  72. user_info.private_rooms.append(canonical_alias or name or room_id)
  73. user_info.ips = DatabasePool.simple_select_onecol_txn(
  74. txn,
  75. table="user_ips",
  76. keyvalues={"user_id": user_info.user_id},
  77. retcol="ip",
  78. )
  79. return user_infos
  80. def main() -> None:
  81. parser = argparse.ArgumentParser()
  82. parser.add_argument(
  83. "-c",
  84. "--config-path",
  85. action="append",
  86. metavar="CONFIG_FILE",
  87. help="The config files for Synapse.",
  88. required=True,
  89. )
  90. parser.add_argument(
  91. "-s",
  92. "--since",
  93. metavar="duration",
  94. help="Specify how far back to review user registrations for, defaults to 7d (i.e. 7 days).",
  95. default="7d",
  96. )
  97. parser.add_argument(
  98. "-e",
  99. "--exclude-emails",
  100. action="store_true",
  101. help="Exclude users that have validated email addresses.",
  102. )
  103. parser.add_argument(
  104. "-u",
  105. "--only-users",
  106. action="store_true",
  107. help="Only print user IDs that match.",
  108. )
  109. parser.add_argument(
  110. "-a",
  111. "--exclude-app-service",
  112. help="Exclude appservice users.",
  113. action="store_true",
  114. )
  115. config = ReviewConfig()
  116. config_args = parser.parse_args(sys.argv[1:])
  117. config_files = find_config_files(search_paths=config_args.config_path)
  118. config_dict = read_config_files(config_files)
  119. config.parse_config_dict(config_dict, "", "")
  120. since_ms = time.time() * 1000 - Config.parse_duration(config_args.since)
  121. exclude_users_with_email = config_args.exclude_emails
  122. exclude_users_with_appservice = config_args.exclude_app_service
  123. include_context = not config_args.only_users
  124. for database_config in config.database.databases:
  125. if "main" in database_config.databases:
  126. break
  127. engine = create_engine(database_config.config)
  128. with make_conn(database_config, engine, "review_recent_signups") as db_conn:
  129. # This generates a type of Cursor, not LoggingTransaction.
  130. user_infos = get_recent_users(db_conn.cursor(), since_ms, exclude_users_with_appservice) # type: ignore[arg-type]
  131. for user_info in user_infos:
  132. if exclude_users_with_email and user_info.emails:
  133. continue
  134. if include_context:
  135. print_public_rooms = ""
  136. if user_info.public_rooms:
  137. print_public_rooms = "(" + ", ".join(user_info.public_rooms[:3])
  138. if len(user_info.public_rooms) > 3:
  139. print_public_rooms += ", ..."
  140. print_public_rooms += ")"
  141. print("# Created:", datetime.fromtimestamp(user_info.creation_ts))
  142. print("# Email:", ", ".join(user_info.emails) or "None")
  143. print("# IPs:", ", ".join(user_info.ips))
  144. print(
  145. "# Number joined public rooms:",
  146. len(user_info.public_rooms),
  147. print_public_rooms,
  148. )
  149. print("# Number joined private rooms:", len(user_info.private_rooms))
  150. print("#")
  151. print(user_info.user_id)
  152. if include_context:
  153. print()
  154. if __name__ == "__main__":
  155. main()