lingthio / Flask-User

Customizable User Authorization & User Management: Register, Confirm, Login, Change username/password, Forgot password and more.
http://flask-user.readthedocs.io/
MIT License
1.06k stars 294 forks source link

Flask-User's UserMixin class breaks Flask-Admin's editor for unqiue fields #259

Open allendoerfer opened 5 years ago

allendoerfer commented 5 years ago

When using Flask-User v1.0, Flask-Admin cannot edit the user object anymore, but shows the "Username already exists" error. Inserting still works fine. When I remove the UserMixin from the class, editing in Flask-Admin works fine.

I know that this has been a common error with Flask-Admin in the past and you (@lingthio) even commented on that very issue.

lingthio commented 5 years ago

Can you please investigate what part of the UserMixin class creates this conflict? -- I don't have a Flask-Admin app at hand. Thanks

caumons commented 5 years ago

Hi!

Thanks to @clarete's answer at https://github.com/flask-admin/flask-admin/issues/782, I've found that the issue is caused by the method override get_id() defined at https://github.com/lingthio/Flask-User/blob/master/flask_user/user_mixin.py#L16.

This overriden method get_id() is called from https://github.com/maxcountryman/flask-login/blob/master/flask_login/mixins.py#L41 and as it always returns a different value, the equalty comparison of the same object always returns False:

>>> u = User.query.get(1)
>>> u.get_id()
'gAAAAABdG435DHtkA0HVk1Nkzzb_TP9rMEk6YcenftZU2NnF3BaxEIyLMRu-6EcbjANHIXVidon0y1K7yeENEAeDPaG85b3rgg'
>>> u.get_id()
'gAAAAABdG437InvA0_j9eNcVbh7XqcgU3XZQ8KX9lTWgx_Mw8QtJSR9FMdOV1J9qlBF8TaOtvc6Tj9qOgRZEtg2uPyYp2L2cKQ'
>>> u == u
False
>>> u != u
True

The default get_id() implementation from flask-login basically returns the id field converted to a string and therefore it doesn't change in every call.

To workaround this issue, I've overriden the __eq__() method at my User class as follows:

    def __eq__(self, other):
        return self.id == other.id if other else False