123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134 |
- # -*- coding: utf-8 -*-
- # Copyright 2019 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.
- # Actions on the hashing_metadata table which is defined in the migration process in
- # sqlitedb.py
- class HashingMetadataStore:
- def __init__(self, sydent):
- self.sydent = sydent
- def get_lookup_pepper(self):
- """Return the value of the current lookup pepper from the db
-
- :return: A pepper if it exists in the database, or None if one does
- not exist
- :rtype: unicode or None
- """
- cur = self.sydent.db.cursor()
- res = cur.execute("select lookup_pepper from hashing_metadata")
- row = res.fetchone()
- if not row:
- return None
- pepper = row[0]
- # Ensure we're dealing with unicode.
- if isinstance(pepper, bytes):
- pepper = pepper.decode("UTF-8")
- return pepper
- def store_lookup_pepper(self, hashing_function, pepper):
- """Stores a new lookup pepper in the hashing_metadata db table and rehashes all 3PIDs
- :param hashing_function: A function with single input and output strings
- :type hashing_function func(str) -> str
- :param pepper: The pepper to store in the database
- :type pepper: str
- """
- cur = self.sydent.db.cursor()
- # Create or update lookup_pepper
- sql = (
- 'INSERT OR REPLACE INTO hashing_metadata (id, lookup_pepper) '
- 'VALUES (0, ?)'
- )
- cur.execute(sql, (pepper,))
- # Hand the cursor to each rehashing function
- # Each function will queue some rehashing db transactions
- self._rehash_threepids(cur, hashing_function, pepper, "local_threepid_associations")
- self._rehash_threepids(cur, hashing_function, pepper, "global_threepid_associations")
- # Commit the queued db transactions so that adding a new pepper and hashing is atomic
- self.sydent.db.commit()
- def _rehash_threepids(self, cur, hashing_function, pepper, table):
- """Rehash 3PIDs of a given table using a given hashing_function and pepper
- A database cursor `cur` must be passed to this function. After this function completes,
- the calling function should make sure to call self`self.sydent.db.commit()` to commit
- the made changes to the database.
- :param cur: Database cursor
- :type cur:
- :param hashing_function: A function with single input and output strings
- :type hashing_function func(str) -> str
- :param pepper: A pepper to append to the end of the 3PID (after a space) before hashing
- :type pepper: str
- :param table: The database table to perform the rehashing on
- :type table: str
- """
- # Get count of all 3PID records
- # Medium/address combos are marked as UNIQUE in the database
- sql = "SELECT COUNT(*) FROM %s" % table
- res = cur.execute(sql)
- row_count = res.fetchone()
- row_count = row_count[0]
- # Iterate through each medium, address combo, hash it,
- # and store in the db
- batch_size = 500
- count = 0
- while count < row_count:
- sql = (
- "SELECT medium, address FROM %s ORDER BY id LIMIT %s OFFSET %s" %
- (table, batch_size, count)
- )
- res = cur.execute(sql)
- rows = res.fetchall()
- for medium, address in rows:
- # Skip broken db entry
- if not medium or not address:
- continue
- # Combine the medium, address and pepper together in the
- # following form: "address medium pepper"
- # According to MSC2134: https://github.com/matrix-org/matrix-doc/pull/2134
- combo = "%s %s %s" % (address, medium, pepper)
- # Hash the resulting string
- result = hashing_function(combo)
- # Save the result to the DB
- sql = (
- "UPDATE %s SET lookup_hash = ? "
- "WHERE medium = ? AND address = ?"
- % table
- )
- # Lines up the query to be executed on commit
- cur.execute(sql, (result, medium, address))
- count += len(rows)
|