dpgaspar / Flask-AppBuilder

Simple and rapid application development framework, built on top of Flask. includes detailed security, auto CRUD generation for your models, google charts and much more. Demo (login with guest/welcome) - http://flaskappbuilder.pythonanywhere.com/
BSD 3-Clause "New" or "Revised" License
4.66k stars 1.36k forks source link

security/manager.py - AttributeError: 'bool' object has no attribute 'login_count' #1329

Open tooptoop4 opened 4 years ago

tooptoop4 commented 4 years ago

2020-03-26 23:44:12,108:ERROR:superset:Exception on /login/ [POST] Traceback (most recent call last): File "/usr/lib64/python3.6/dist-packages/flask/app.py", line 2446, in wsgi_app response = self.full_dispatch_request() File "/usr/lib64/python3.6/dist-packages/flask/app.py", line 1951, in full_dispatch_request rv = self.handle_user_exception(e) File "/usr/lib64/python3.6/dist-packages/flask/app.py", line 1820, in handle_user_exception reraise(exc_type, exc_value, tb) File "/usr/lib64/python3.6/dist-packages/flask/_compat.py", line 39, in reraise raise value File "/usr/lib64/python3.6/dist-packages/flask/app.py", line 1949, in full_dispatch_request rv = self.dispatch_request() File "/usr/lib64/python3.6/dist-packages/flask/app.py", line 1935, in dispatch_request return self.view_functionsrule.endpoint File "/usr/lib64/python3.6/dist-packages/flask_appbuilder/security/views.py", line 515, in login form.username.data, form.password.data File "/usr/lib64/python3.6/dist-packages/flask_appbuilder/security/manager.py", line 943, in auth_user_ldap self.update_user_auth_stat(user) File "/usr/lib64/python3.6/dist-packages/flask_appbuilder/security/manager.py", line 737, in update_user_auth_stat if not user.login_count: AttributeError: 'bool' object has no attribute 'login_count'

python3 -m pip freeze alembic==1.4.2 amqp==2.5.2 apache-superset==0.35.2 apispec==1.3.3 attrs==19.3.0 Babel==2.8.0 backoff==1.10.0 billiard==3.6.3.0 bleach==3.1.4 boto3==1.12.29 botocore==1.15.29 celery==4.4.2 certifi==2019.11.28 cffi==1.14.0 chardet==3.0.4 click==6.7 colorama==0.4.3 contextlib2==0.6.0.post1 croniter==0.3.31 cryptography==2.8 decorator==4.4.2 defusedxml==0.6.0 docutils==0.15.2 Flask==1.1.1 Flask-AppBuilder==2.2.4 Flask-Babel==1.0.0 Flask-Caching==1.8.0 Flask-Compress==1.4.0 Flask-JWT-Extended==3.24.1 Flask-Login==0.4.1 Flask-Migrate==2.5.3 Flask-OpenID==1.2.5 Flask-SQLAlchemy==2.4.1 flask-talisman==0.7.0 Flask-WTF==0.14.3 future==0.18.2 geographiclib==1.50 geopy==1.21.0 gunicorn==19.8.1 humanize==2.2.0 idna==2.9 importlib-metadata==1.5.2 isodate==0.6.0 itsdangerous==1.1.0 Jinja2==2.11.1 jmespath==0.9.5 jsonschema==3.2.0 kombu==4.6.8 ldap3==2.7 Mako==1.1.2 Markdown==3.2.1 MarkupSafe==1.1.1 marshmallow==2.19.5 marshmallow-enum==1.5.1 marshmallow-sqlalchemy==0.22.3 msgpack==0.6.2 numpy==1.18.2 pandas==0.24.2 parsedatetime==2.5 pathlib2==2.3.5 polyline==1.4.0 prison==0.1.3 py==1.8.1 py4j==0.10.7 pyarrow==0.15.1 pyasn1==0.4.8 pyasn1-modules==0.2.8 pycparser==2.20 PyHive==0.6.2 PyJWT==1.7.1 pyldap==3.0.0.post1 pypandoc==1.4 pyrsistent==0.16.0 pyspark==2.3.4 python-dateutil==2.8.1 python-dotenv==0.12.0 python-editor==1.0.4 python-geohash==0.8.5 python-ldap==3.2.0 python3-openid==3.1.0 pytz==2019.3 PyYAML==5.3.1 requests==2.23.0 retry==0.9.2 s3transfer==0.3.3 selenium==3.141.0 simplejson==3.17.0 six==1.14.0 SQLAlchemy==1.3.15 SQLAlchemy-Utils==0.36.3 sqlparse==0.3.1 urllib3==1.25.8 vine==1.3.0 webencodings==0.5.1 Werkzeug==1.0.0 WTForms==2.2.1 WTForms-JSON==0.3.3 zipp==3.1.0

Python 3.6.10 (default, Feb 10 2020, 19:55:14) [GCC 4.8.5 20150623 (Red Hat 4.8.5-28)] on linux

dpgaspar commented 4 years ago

Hi @tooptoop4,

Can you please add more context, how can I reproduce this?

tooptoop4 commented 4 years ago

@dpgaspar

sudo -i
yum install gcc gcc-c++ libffi-devel openssl-devel libsasl2-devel openldap-devel -y
python3 -m pip install apache-superset==0.35.2
python3 -m pip install pyhive[presto]
#put the attached config_github.txt into /usr/lib/python3.6/dist-packages/superset/config.py
python3 -m pip install pyldap
superset db upgrade
export FLASK_APP=superset
flask fab create-admin --username auser --firstname auser --lastname auser --email anemail --password 'apass'
superset init
superset run --host 0.0.0.0 -p 8786 --with-threads --reload --debugger
go to http://myhostname:8786
enter another users credentials, error will appear in the logs and ui
python3 -m pip install ldap3
superset run --host 0.0.0.0 -p 8786 --with-threads --reload --debugger
go to http://myhostname:8786
enter another users credentials, error will appear in the logs and ui
python3 -m pip install python-ldap
superset run --host 0.0.0.0 -p 8786 --with-threads --reload --debugger
go to http://myhostname:8786
enter another users credentials, error will appear in the logs and ui

config_github.txt

dpgaspar commented 4 years ago

Ok, so your using:

AUTH_TYPE = AUTH_LDAP
AUTH_ROLE_ADMIN = 'Admin'
AUTH_USER_REGISTRATION = True
AUTH_USER_REGISTRATION_ROLE = "admin"

I'll try to reproduce, meanwhile can you check if the same happens with AUTH_USER_REGISTRATION = False (you have to register LDAP users on the DB)

tooptoop4 commented 4 years ago

fresh install using original config.py attached before

2020-03-27 22:06:16,005:ERROR:flask_appbuilder.security.sqla.manager:Error adding new user to database. Can't flush None value found in collection User.roles
Exception on /login/ [POST]
Traceback (most recent call last):
  File "/usr/lib64/python3.6/dist-packages/flask/app.py", line 2446, in wsgi_app
    response = self.full_dispatch_request()
  File "/usr/lib64/python3.6/dist-packages/flask/app.py", line 1951, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/usr/lib64/python3.6/dist-packages/flask/app.py", line 1820, in handle_user_exception
    reraise(exc_type, exc_value, tb)
  File "/usr/lib64/python3.6/dist-packages/flask/_compat.py", line 39, in reraise
    raise value
  File "/usr/lib64/python3.6/dist-packages/flask/app.py", line 1949, in full_dispatch_request
    rv = self.dispatch_request()
  File "/usr/lib64/python3.6/dist-packages/flask/app.py", line 1935, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "/usr/lib64/python3.6/dist-packages/flask_appbuilder/security/views.py", line 515, in login
    form.username.data, form.password.data
  File "/usr/lib64/python3.6/dist-packages/flask_appbuilder/security/manager.py", line 943, in auth_user_ldap
    self.update_user_auth_stat(user)
  File "/usr/lib64/python3.6/dist-packages/flask_appbuilder/security/manager.py", line 737, in update_user_auth_stat
    if not user.login_count:
AttributeError: 'bool' object has no attribute 'login_count'
2020-03-27 22:06:16,005:ERROR:superset:Exception on /login/ [POST]
Traceback (most recent call last):
  File "/usr/lib64/python3.6/dist-packages/flask/app.py", line 2446, in wsgi_app
    response = self.full_dispatch_request()
  File "/usr/lib64/python3.6/dist-packages/flask/app.py", line 1951, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/usr/lib64/python3.6/dist-packages/flask/app.py", line 1820, in handle_user_exception
    reraise(exc_type, exc_value, tb)
  File "/usr/lib64/python3.6/dist-packages/flask/_compat.py", line 39, in reraise
    raise value
  File "/usr/lib64/python3.6/dist-packages/flask/app.py", line 1949, in full_dispatch_request
    rv = self.dispatch_request()
  File "/usr/lib64/python3.6/dist-packages/flask/app.py", line 1935, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "/usr/lib64/python3.6/dist-packages/flask_appbuilder/security/views.py", line 515, in login
    form.username.data, form.password.data
  File "/usr/lib64/python3.6/dist-packages/flask_appbuilder/security/manager.py", line 943, in auth_user_ldap
    self.update_user_auth_stat(user)
  File "/usr/lib64/python3.6/dist-packages/flask_appbuilder/security/manager.py", line 737, in update_user_auth_stat
    if not user.login_count:
AttributeError: 'bool' object has no attribute 'login_count'
tooptoop4 commented 4 years ago

success now! the cause is due to case sensitivity AUTH_USER_REGISTRATION_ROLE = "admin" should be AUTH_USER_REGISTRATION_ROLE = "Admin"

to avoid this in future i can think of 3 items: more documentation on case sensitivity Perhaps the config.py should get auto rejected if invalid role or better error message than "AttributeError: 'bool' object has no attribute 'login_count'"

dpgaspar commented 4 years ago

Glad to ear it, going to label this has a bug since the error message is not helpful at all

tooptoop4 commented 4 years ago

@dpgaspar any idea on how i can fix https://github.com/apache/incubator-superset/issues/7170 ?

grumbler commented 3 years ago

In my case (airflow) there was another exception before, unique constraint violation while trying to insert user entry. in the security/manager.py auth_user_ldap function tries to insert user: user = self.add_user(...

but it gets back False in case of error: sqla/manager.py function add_user and this leads to the exception above as auth_user_ldap doesn't check for the return value and directly calls update_user_auth_stat

flask_appbuilder version = "3.1.1"

tooptoop4 commented 3 years ago

@grumbler which airflow version?

grumbler commented 3 years ago

@tooptoop4 2.0.1

rshark commented 3 years ago

I got this error when I config AUTH_USER_REGISTRATION_ROLE = 'Veiwer'

anumoy commented 3 years ago

@rshark Where you able to fix the issue.. Just asking as I am also getting the same issue.

anumoy commented 3 years ago

I changed AUTH_USER_REGISTRATION_ROLE to "Admin" from "Viewer" and visa versa. Also tried commenting it out. Nothing is working for me. Python ver 3.7.1 Airflow ver 2.0.1 Python-ldap ver 3.3.1

anumoy commented 3 years ago

I changed AUTH_USER_REGISTRATION_ROLE to "Admin" from "Viewer" and visa versa. Also tried commenting it out. Nothing is working for me. Python ver 3.7.1 Airflow ver 2.0.1 Python-ldap ver 3.3.1

Sorry for the delayed response. I was able to resolve this issue in my case. By going through the webserver logs. The RCA was the user I was trying to login with after doing the LDAP changes has an entry into the User table already.

I would suggest before deploying any changes to the login / authentication process in the webserver config, try removing all entry to the user and user role mapping tables. So that after the deployment the flask app builder will create the user's with new configuration and authentication.

Hope this helps some of the people's.

Swalloow commented 2 years ago

In my case, it was caused by schema mismatch after DB change. Adjusting the LOG_LEVEL will help you understand.