Welcome to the Question2Answer Q&A. There's also a demo if you just want to try it out.
+4 votes
in Plugins by

This is a request for a feature at the code level, which could be used by plugin developers

Q2A core has a function to delete an user account from the database, which, besides removing the entry from qa_users table, updates all the other tables which have references to the user. However, there is no way for a plugin developer to safely merge 2 user accounts (move all points/activity/content from one user to another). While this could theoretically be implemented in a plugin, it might be better to have it in the Q2A core, in case new tables are added and/or removed in the future.

Would such a functionality be feasible? If yes, I could start implementing it and provide a patch.

Reason for requesting this: improve the open-login plugin with the ability to merge duplicate accounts




2 Answers

0 votes
I don't think this should get to the core. Merging accounts is a weird concept and if you think in detail it might be not only hard but most likely impossible to properly implement. Let's think of a simple example: A user earns a badge for a given question (using a badge plugin) then the user logs in with a different username and earns the same badge for the same question with the other user. Would that  mean the user has earned 2 times the same badge? Does it make sense for the core and each plugin to handle that awkward situation?

Let's think of a simpler approach. If I'm guessing correctly, the issue here is that you have one real life person that wants to login with different providers... make it facebook, google, whatever. So, my guess, is that every plugin creates a different user for each provider (is this correct?). I haven't taken a look at the code (and I can't do that right now) but the ideal approach in terms of backwards compatibility would be to try to use the provider column in the users table (I don't remember its name... was it source?) and as a column holding N values and changing the way it is accessed (probably with some overrides?).

Denormalizing the table that way you should be able to model the ideal solution which, if I'm correct, would be a one-to-many relationship between users and providers.

Having said that, there is the more normalized apprach which will, most likely, requiere changes to the core. Thinking it carefully, those changes could even be backwards compatible too. The idea would be to have the users table, remove the source column, and then have a different table to join with that will have an FK to the users table and the providers. There you'll have your one-to-many relationship and this issue would be 100% transparently solved for any other plugin... and even to the rest of the core as that would only affect the login/registration and maybe accounts sections. The rest of the core and plugins will always operate on the handle/userid which are part of the users table.

I'm just thinking in a loud voice... but probably giving you some ideas :)
Thanks for your feedback. Well, the need for merging 2 accounts comes when there already are 2 accounts created for the same real person.

The code is already linking multiple providers to the same real person (when the user explicitly requests to add more providers to his account, from "My logins" page), however it is also possible for the same person to login with a different provider (from the login/register pages), which creates a brand new q2a account.

The plug-in tries to detect that situation, (looking if there are similar [verified] email addresses) and proposes the merger of the duplicate accounts. Currently, merging means that one q2a account is deleted (all its activity being marked as anonymous) and the other account gets all external login providers.

However, it would be more natural to be able to keep all the activity & points from the account which is being merged in (deleted), so this is why I'm requesting such an enhancement.

Let me know if you need more details on this.

Everything looks fine until the "The plug-in tries to detect that situation". I think there should be a hook (if possible) that would handle this situation before the account is created. So when someone tries to register you check their email address that you get from the provider (assuming the user has actually authenticated) against the ^users table. If found and validated, then just add a new provider for the given account. If not found and validated then create a new user.

That way you can dodge the merging of accounts in advance. Anyway, what I can't confirm that is possible (I bet there is some way, though) is actually finding a decent place to hook this event handler.
So you say it should automatically do the merge without asking for their confirmation? I don't know if that would be a good approach. The user should at least know that.

However, this only solves part of the problem. For unconfirmed emails, there will still be duplicate accounts and if the users wants to manually link the 2 separate accounts (through the "my logins" page) there will still be the need for a merge functionality.

So, even if there might be situations where you can avoid creating duplicate accounts (if different approach is used, as you suggested), in the end users might still end up having duplicates, due to the fact that not all providers return an email address, or even to the fact that a real person might use different email addresses for different services. For these situations we need the ability to merge accounts (with or without loosing data).

Also, there might be cases when users just want to log in to be able to, for example, post a comment and they might not care about duplicates. It's their right to do so, even though not a pleasant situation for the site admin. In this case, the plugin should allow the user to have his duplicate account created, so the user can mind his own way. In this case, in my opinion, it is better to have a duplicate account who posts content to your site (be that a comment), than have no account at all, and no new content.

However, I retain your idea to do the duplicate detection before creating a new account. It was actually one of the approaches I took into account when designing the plugin, but I decided to take the other safer path. It's easier to miss a registration when you're creating the account after a few required steps. Conversely, it's safer to have the account created from the beginning and propose to the user some optional steps. This way, even if he changes his mind halfway through the process and cancels those optional steps you still have his account (and details) saved. We live in a greedy world :)

Thanks again for the feedback and for the time to look into this!
No need to say thanks... you're helping others with this plugin :)

I see now what the issue is and it might go a bit further than just merging or not accounts. I think the issue actually is "How to determine for 2 different accounts if they share the same human being?" :) IMO, and also taking a look at how stackoverflow handles this, there is only one approach: the email address. I think there are only 2 cases in which a user could link 2 accounts:

1. A user registers with a facebook provider and facebook returns a@a.com. So you add that email address for the user. The user logs out. Then the human being tries to register using twitter. If the email twitter returns is also a@a.com there is no need to ask/warn for a merge because, on one hand, there is no merge as no 2 accounts exist yet and, on the other hand, because the 2 emails are the same and are validated so it is indeed the same human being sitting in front of the computer

2. A user registers with facebook provider using a@a.com. Being logged in, the user finds an option in their profile that would allow them to link their account to another email address. So the user clicks on that link, is requested a set of providers to link with and then the user executes this process. The user should be able to choose which would be the primary email address for Q2A (that would be the one that would allow the user to login with their email address on the site... right now Q2A does not support multiple email addresses)

Regarding unconfirmed emails, I personally, wouldn't allow users to post anything if they haven't confirmed their emails. Probably the plugin should have an option to allow linking/registering accounts with unconfirmed emails. If the provider returns the email address everything is fine. If the provider doesn't return the email address (I didn't know some didn't... which ones are them? AFAIK, lightopenid allows you to force this... not sure about how twitter handles this) and the admin allowed unconfirmed emails, taking Stackoveflow's approach the user would be able to use the site normally.

Now, to continue with unconfirmed emails, consider the following situation. User A said they owned email a@a.com. User B is the real owner of that email address. User B tries to register using that email address. Currently, Q2A will not allow this to happen (I don't like this but that's the way the core works). You should take that into account and handle this situation according to the core rules whenever a user tries to register with an existent account.

So you can avoid merging accounts for unconfirmed emails. Now in the case a user registers with 2 different email addresses per provider then the user is asking for it: 2 different users have to be created. Try that on stackoverflow. It is exactly the same situation as registering twice with different emails: 2 different accounts will have to be created. An awkward situation might happen though. You have these 2 accounts registered and in one of them you go to your profile page and then you request to link your account to the same email address on your other account. This would be the closest thing to a merge situation because it is OK for those 2 accounts to exist but the linking can't be done without removing the other account. Having said that, stackoverflow's approach is to not allow this linking and asking the user to logout their current account and login as the other one or just cancel the operation. I absolutely agree with this. Removing or merging users is, IMO, a no go and will bring a lot of trouble, questions and doubts to users.

Hopefully this has clarified how I think this plugin should behave. Anyway, if I were you I'd have a list of all possible situations to handle considering different core settings such as unconfirmed emails or login only allowed by email. Probably decision tables would help you with that http://en.wikipedia.org/wiki/Decision_table . Keep it up :)
0 votes
I think this is a very good feature. Is there a good way to do this?