Currently, many objects have a mailKey field, and copy/pasted logic to populate it. This key is used as a seed to generate unique addresses for each <object, user> pair so that I send mail to T123+1+abe2h3f2 and you send mail to T123+2+fo1m213n and I can't just fiddle with my "+1" and impersonate someone else.
This could much more simply be a Mail table which stores <objectPHID, mailKey> and generates new keys lazily on first use.
This would allow us to remove a substantial amount of copy/pasted code:
epriestley@orbital ~/dev/phabricator $ git grep -i mailkey src/applications/almanac/storage/AlmanacBinding.php: protected $mailKey; src/applications/almanac/storage/AlmanacBinding.php: 'mailKey' => 'bytes20', src/applications/almanac/storage/AlmanacBinding.php: if (!$this->mailKey) { src/applications/almanac/storage/AlmanacBinding.php: $this->mailKey = Filesystem::readRandomCharacters(20); src/applications/almanac/storage/AlmanacDevice.php: protected $mailKey; src/applications/almanac/storage/AlmanacDevice.php: 'mailKey' => 'bytes20', src/applications/almanac/storage/AlmanacDevice.php: if (!$this->mailKey) { src/applications/almanac/storage/AlmanacDevice.php: $this->mailKey = Filesystem::readRandomCharacters(20); src/applications/almanac/storage/AlmanacNamespace.php: protected $mailKey; src/applications/almanac/storage/AlmanacNamespace.php: 'mailKey' => 'bytes20', src/applications/almanac/storage/AlmanacNamespace.php: if (!$this->mailKey) { src/applications/almanac/storage/AlmanacNamespace.php: $this->mailKey = Filesystem::readRandomCharacters(20); src/applications/almanac/storage/AlmanacNetwork.php: protected $mailKey; src/applications/almanac/storage/AlmanacNetwork.php: 'mailKey' => 'bytes20', src/applications/almanac/storage/AlmanacNetwork.php: if (!$this->mailKey) { src/applications/almanac/storage/AlmanacNetwork.php: $this->mailKey = Filesystem::readRandomCharacters(20); src/applications/almanac/storage/AlmanacService.php: protected $mailKey; src/applications/almanac/storage/AlmanacService.php: 'mailKey' => 'bytes20', src/applications/almanac/storage/AlmanacService.php: if (!$this->mailKey) { ...
This change needs to keep mail keys stable, so all the existing mail keys should be copied into the new table before they are deleted.
There should be a very small number of readers (2-3?) of this field, so it should be possible to build them safely like this:
- If the object is a lisk object with a mailKey property, continue calling getMailKey().
- Otherwise, read the new mail key table; use the result if a row exists.
- Otherwise, insert a new result into the table; use that.
Then copy and remove all the mailKey properties one by one until we can delete the chunk of code in (1).