123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179 |
- # Copyright 2021 The Matrix.org Foundation C.I.C.
- #
- # Licensed under the Apache License, Version 2.0 (the "License");
- # you may not use this file except in compliance with the License.
- # You may obtain a copy of the License at
- #
- # http://www.apache.org/licenses/LICENSE-2.0
- #
- # Unless required by applicable law or agreed to in writing, software
- # distributed under the License is distributed on an "AS IS" BASIS,
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- # See the License for the specific language governing permissions and
- # limitations under the License.
- import argparse
- import sys
- import time
- from datetime import datetime
- from typing import List
- import attr
- from synapse.config._base import (
- Config,
- RootConfig,
- find_config_files,
- read_config_files,
- )
- from synapse.config.database import DatabaseConfig
- from synapse.storage.database import DatabasePool, LoggingTransaction, make_conn
- from synapse.storage.engines import create_engine
- class ReviewConfig(RootConfig):
- "A config class that just pulls out the database config"
- config_classes = [DatabaseConfig]
- @attr.s(auto_attribs=True)
- class UserInfo:
- user_id: str
- creation_ts: int
- emails: List[str] = attr.Factory(list)
- private_rooms: List[str] = attr.Factory(list)
- public_rooms: List[str] = attr.Factory(list)
- ips: List[str] = attr.Factory(list)
- def get_recent_users(txn: LoggingTransaction, since_ms: int) -> List[UserInfo]:
- """Fetches recently registered users and some info on them."""
- sql = """
- SELECT name, creation_ts FROM users
- WHERE
- ? <= creation_ts
- AND deactivated = 0
- """
- txn.execute(sql, (since_ms / 1000,))
- user_infos = [UserInfo(user_id, creation_ts) for user_id, creation_ts in txn]
- for user_info in user_infos:
- user_info.emails = DatabasePool.simple_select_onecol_txn(
- txn,
- table="user_threepids",
- keyvalues={"user_id": user_info.user_id, "medium": "email"},
- retcol="address",
- )
- sql = """
- SELECT room_id, canonical_alias, name, join_rules
- FROM local_current_membership
- INNER JOIN room_stats_state USING (room_id)
- WHERE user_id = ? AND membership = 'join'
- """
- txn.execute(sql, (user_info.user_id,))
- for room_id, canonical_alias, name, join_rules in txn:
- if join_rules == "public":
- user_info.public_rooms.append(canonical_alias or name or room_id)
- else:
- user_info.private_rooms.append(canonical_alias or name or room_id)
- user_info.ips = DatabasePool.simple_select_onecol_txn(
- txn,
- table="user_ips",
- keyvalues={"user_id": user_info.user_id},
- retcol="ip",
- )
- return user_infos
- def main():
- parser = argparse.ArgumentParser()
- parser.add_argument(
- "-c",
- "--config-path",
- action="append",
- metavar="CONFIG_FILE",
- help="The config files for Synapse.",
- required=True,
- )
- parser.add_argument(
- "-s",
- "--since",
- metavar="duration",
- help="Specify how far back to review user registrations for, defaults to 7d (i.e. 7 days).",
- default="7d",
- )
- parser.add_argument(
- "-e",
- "--exclude-emails",
- action="store_true",
- help="Exclude users that have validated email addresses",
- )
- parser.add_argument(
- "-u",
- "--only-users",
- action="store_true",
- help="Only print user IDs that match.",
- )
- config = ReviewConfig()
- config_args = parser.parse_args(sys.argv[1:])
- config_files = find_config_files(search_paths=config_args.config_path)
- config_dict = read_config_files(config_files)
- config.parse_config_dict(
- config_dict,
- )
- since_ms = time.time() * 1000 - Config.parse_duration(config_args.since)
- exclude_users_with_email = config_args.exclude_emails
- include_context = not config_args.only_users
- for database_config in config.database.databases:
- if "main" in database_config.databases:
- break
- engine = create_engine(database_config.config)
- with make_conn(database_config, engine, "review_recent_signups") as db_conn:
- user_infos = get_recent_users(db_conn.cursor(), since_ms)
- for user_info in user_infos:
- if exclude_users_with_email and user_info.emails:
- continue
- if include_context:
- print_public_rooms = ""
- if user_info.public_rooms:
- print_public_rooms = "(" + ", ".join(user_info.public_rooms[:3])
- if len(user_info.public_rooms) > 3:
- print_public_rooms += ", ..."
- print_public_rooms += ")"
- print("# Created:", datetime.fromtimestamp(user_info.creation_ts))
- print("# Email:", ", ".join(user_info.emails) or "None")
- print("# IPs:", ", ".join(user_info.ips))
- print(
- "# Number joined public rooms:",
- len(user_info.public_rooms),
- print_public_rooms,
- )
- print("# Number joined private rooms:", len(user_info.private_rooms))
- print("#")
- print(user_info.user_id)
- if include_context:
- print()
- if __name__ == "__main__":
- main()
|