Date: 2023-03-17
Accepted (lazy consensus).
Implemented.
Changing username is a desired feature for an email server. It is a common practice especially when a user marries or divorces. For example:
Alice MARTINEZ have an email address alice.martinez@domain.tld
and gets married to Bob ERNANDEZ. She thus wants to change her email address to alice.ernandez@domain.tld
while preserving her email data.
Nowadays, James uses username as an identifier for user data. Therefore, this feature is hard to implement because of changing directly identifier to another value is difficult and could break data consistency if we do not do it carefully.
We decided to do changing username with two steps: first, create new username, then migrate the old user's data to the new account - the way we expect that is less dangerous to current data consistency. The data in the old account need to be truncated after migrating to the new account.
For the data migration step, we decided to form it under a webadmin task with a modular design. A big data migration task contains many small tasks that implement UsernameChangeTaskStep
interface. This modular design for migration steps could help developers easier to manage/test each step, and help other tailor James servers can implement their own steps as well.
Today, implemented migration steps are:
ForwardUsernameChangeTaskStep
: creates forward from the old user to the new user and migrates existing forwardsFilterUsernameChangeTaskStep
: migrates users filtering rulesDelegationUsernameChangeTaskStep
: migrates delegations where the impacted user is either delegatee or delegatorMailboxUsernameChangeTaskStep
: migrates mailboxes belonging to the old user to the account of the new user. It also migrates users' mailbox subscriptions.ACLUsernameChangeTaskStep
: migrates ACLs on mailboxes the migrated user has access to and updates subscriptions accordingly.We introduce fromStep
query parameter that allows skipping previous steps, allowing the operator to resume the username change from a failed step. This option could ease operators in case the data migration fails in the middle.
We could have another choice for implementing this topic: create an account identifier not linked directly to the username (e.g a hash value points to a username), so changing the pointer value would be easier than changing the pointer itself. However, that approach has two great concerns: