flask-security
flask-security copied to clipboard
Use user.get_id() instead of user.id
https://github.com/mattupstate/flask-security/blob/a0e203774795f1bad289d76357237fcb604bfa01/flask_security/utils.py#L82
Isn't the whole point of Flask-Login interface for get_id() to avoid calling an id attribute directly? I'm implementing a backend for Google datastore which does not have id attibute.
I'm just playing around with Flask-Security as well, and have run into this issue. I have a legacy DB with no "id" field. So Flask-Security won't work there :(
Flask-Security uses id in several places, and the docs state that it is a required field of User objects. To get around the issue of not having an id on your user model, you can simply add id as a property and return whatever your actual identifier is.
class User(UserDatastore):
"""Custom Flask-Security-compatible user model."""
...
@property
def id(self):
"""Return an identifier."""
return self.unique_identifier
I can't speak to the author's intention with Flask-Login's get_id, but it seems that it exists as much to convert other types to unicode as it does to abstract away an id field; it's effectively just a wrapper unicode(user.id).
@jonafato After having a good night's sleep, I had the same idea. Wasn't sure if flask-security expected an int though. Just blindly tested and it works.
@jimbojetlag Can you test if that works as well for you and let us know? If yes, this issue could be considered closed if that's okay with you?
Cheers.
I ended up with the same solution myself. I'm closing this issue, but I do not find the interface consistent.
It seems this does not work after all. I've been hunting a login-bug in my application for the past two days now, and traced it back to my classes not having the default id attribute.
I've created a gist with a working and broken example. The only difference is the id attribute on both the role and user tables.
@jimbojetlag Did you only add the "property"? Or did you do anything else to make it work? If it turns out that it's because of the id field, then I guess this issue needs to be reopened.
I forgot to mention that I also had to override a module function in a dirty way:
from flask.ext.principal import UserNeed
def _on_identity_loaded(sender, identity):
if hasattr(current_user, 'id'):
identity.provides.add(UserNeed(current_user.id))
identity.user = current_user
flask_security_core._on_identity_loaded = _on_identity_loaded
Hmmm... this did not make any difference for me. From what I can tell, comparing to the original _on_identity_loaded method, you only removed the roles. I've stepped through the original method in core.py, and it looks like it does the right thing. The Identity object is properly created (with the correct values).
I only realised that auth_type is None. But looking through flask-security, the Identity constructor is actually used with the default constructor which also sets auth_type to None. So that does not look to be the source of the problem... I think.
I still don't quite see where the problem comes from :(
Hello, I found this issue after hours trying to find out, why I am not able to confirm my account with a generated token.
The only problem is missing id field in SQLAlchemy DB, because the get_token_status function uses datastore.find_user instead of datastore.get_user, which is simply SQL filter on id field.
Do you have some workaround? I do not like using generic id field in the database... This could be at least configurable, as other model related options.
@MartinMikita what is your primary key in User table?
Field account_id, why?
Can you create an alias property id for it, since Flask-Security expects this property to exists?
@jirikuncar Could you, please, read my post again and carefully? It is NOT expected property, but it is using SQL .filter_by(id=value), this will not use alias property in the model! I have it, and it is not working, therefore I wrote it here.
This is the only code in the method get_token_status(), where it is used in this way...
@MartinMikita it would be easier if you provide the whole definition of your model.
Following example should work for you:
from sqlalchemy.orm import synonym
class User(db.Model, UserMixin):
account_id = Column(...)
...
id = synonym('account_id')
PS: I am trying to help you in my free time so be patient 😉
Sorry, I haven't heard of synonym from SQLAlchemy before. I was using python property as an alias.
@jirikuncar they synonym actually worked for me. Thank you!
id = synonym('account_id')
Thank you for the synonym solution