Repository: incubator-airflow
Updated Branches:
  refs/heads/master b6f9ba9cc -> 7cba83333


[AIRFLOW-2181] Convert password_auth and test_password_endpoints from DOS to 
UNIX

Closes #3102 from dan-sf/AIRFLOW-2181


Project: http://git-wip-us.apache.org/repos/asf/incubator-airflow/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-airflow/commit/7cba8333
Tree: http://git-wip-us.apache.org/repos/asf/incubator-airflow/tree/7cba8333
Diff: http://git-wip-us.apache.org/repos/asf/incubator-airflow/diff/7cba8333

Branch: refs/heads/master
Commit: 7cba83333c5227ce37967c65d189a5e994898c68
Parents: b6f9ba9
Author: dan-sf <fowler...@gmail.com>
Authored: Wed Mar 7 09:49:48 2018 +0100
Committer: Fokko Driesprong <fokkodriespr...@godatadriven.com>
Committed: Wed Mar 7 09:49:48 2018 +0100

----------------------------------------------------------------------
 airflow/contrib/auth/backends/password_auth.py  | 418 +++++++++----------
 .../api/experimental/test_password_endpoints.py | 162 +++----
 2 files changed, 290 insertions(+), 290 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-airflow/blob/7cba8333/airflow/contrib/auth/backends/password_auth.py
----------------------------------------------------------------------
diff --git a/airflow/contrib/auth/backends/password_auth.py 
b/airflow/contrib/auth/backends/password_auth.py
index 33f3ae0..cfb921c 100644
--- a/airflow/contrib/auth/backends/password_auth.py
+++ b/airflow/contrib/auth/backends/password_auth.py
@@ -1,209 +1,209 @@
-# -*- coding: utf-8 -*-
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-from __future__ import unicode_literals
-
-from sys import version_info
-
-import base64
-import flask_login
-from flask_login import current_user
-from flask import flash, Response
-from wtforms import Form, PasswordField, StringField
-from wtforms.validators import InputRequired
-from functools import wraps
-
-from flask import url_for, redirect, make_response
-from flask_bcrypt import generate_password_hash, check_password_hash
-
-from sqlalchemy import Column, String
-from sqlalchemy.ext.hybrid import hybrid_property
-
-from airflow import settings
-from airflow import models
-from airflow.utils.db import provide_session
-from airflow.utils.log.logging_mixin import LoggingMixin
-
-login_manager = flask_login.LoginManager()
-login_manager.login_view = 'airflow.login'  # Calls login() below
-login_manager.login_message = None
-
-log = LoggingMixin().log
-PY3 = version_info[0] == 3
-
-
-class AuthenticationError(Exception):
-    pass
-
-
-class PasswordUser(models.User):
-    _password = Column('password', String(255))
-
-    def __init__(self, user):
-        self.user = user
-
-    @hybrid_property
-    def password(self):
-        return self._password
-
-    @password.setter
-    def _set_password(self, plaintext):
-        self._password = generate_password_hash(plaintext, 12)
-        if PY3:
-            self._password = str(self._password, 'utf-8')
-
-    def authenticate(self, plaintext):
-        return check_password_hash(self._password, plaintext)
-
-    def is_active(self):
-        '''Required by flask_login'''
-        return True
-
-    def is_authenticated(self):
-        '''Required by flask_login'''
-        return True
-
-    def is_anonymous(self):
-        '''Required by flask_login'''
-        return False
-
-    def get_id(self):
-        '''Returns the current user id as required by flask_login'''
-        return str(self.id)
-
-    def data_profiling(self):
-        '''Provides access to data profiling tools'''
-        return True
-
-    def is_superuser(self):
-        '''Access all the things'''
-        return True
-
-
-@login_manager.user_loader
-@provide_session
-def load_user(userid, session=None):
-    log.debug("Loading user %s", userid)
-    if not userid or userid == 'None':
-        return None
-
-    user = session.query(models.User).filter(models.User.id == 
int(userid)).first()
-    return PasswordUser(user)
-
-
-def authenticate(session, username, password):
-    """
-    Authenticate a PasswordUser with the specified
-    username/password.
-
-    :param session: An active SQLAlchemy session
-    :param username: The username
-    :param password: The password
-
-    :raise AuthenticationError: if an error occurred
-    :return: a PasswordUser
-    """
-    if not username or not password:
-        raise AuthenticationError()
-
-    user = session.query(PasswordUser).filter(
-        PasswordUser.username == username).first()
-
-    if not user:
-        raise AuthenticationError()
-
-    if not user.authenticate(password):
-        raise AuthenticationError()
-
-    log.info("User %s successfully authenticated", username)
-    return user
-
-
-@provide_session
-def login(self, request, session=None):
-    if current_user.is_authenticated():
-        flash("You are already logged in")
-        return redirect(url_for('admin.index'))
-
-    username = None
-    password = None
-
-    form = LoginForm(request.form)
-
-    if request.method == 'POST' and form.validate():
-        username = request.form.get("username")
-        password = request.form.get("password")
-
-    try:
-        user = authenticate(session, username, password)
-        flask_login.login_user(user)
-
-        return redirect(request.args.get("next") or url_for("admin.index"))
-    except AuthenticationError:
-        flash("Incorrect login details")
-        return self.render('airflow/login.html',
-                           title="Airflow - Login",
-                           form=form)
-    finally:
-        session.commit()
-        session.close()
-
-
-class LoginForm(Form):
-    username = StringField('Username', [InputRequired()])
-    password = PasswordField('Password', [InputRequired()])
-
-
-def _unauthorized():
-    """
-    Indicate that authorization is required
-    :return:
-    """
-    return Response("Unauthorized", 401, {"WWW-Authenticate": "Basic"})
-
-
-def _forbidden():
-    return Response("Forbidden", 403)
-
-
-def init_app(app):
-    pass
-
-
-def requires_authentication(function):
-    @wraps(function)
-    def decorated(*args, **kwargs):
-        from flask import request
-
-        header = request.headers.get("Authorization")
-        if header:
-            userpass = ''.join(header.split()[1:])
-            username, password = 
base64.b64decode(userpass).decode("utf-8").split(":", 1)
-
-            session = settings.Session()
-            try:
-                authenticate(session, username, password)
-
-                response = function(*args, **kwargs)
-                response = make_response(response)
-                return response
-
-            except AuthenticationError:
-                return _forbidden()
-
-            finally:
-                session.commit()
-                session.close()
-        return _unauthorized()
-    return decorated
+# -*- coding: utf-8 -*-
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from __future__ import unicode_literals
+
+from sys import version_info
+
+import base64
+import flask_login
+from flask_login import current_user
+from flask import flash, Response
+from wtforms import Form, PasswordField, StringField
+from wtforms.validators import InputRequired
+from functools import wraps
+
+from flask import url_for, redirect, make_response
+from flask_bcrypt import generate_password_hash, check_password_hash
+
+from sqlalchemy import Column, String
+from sqlalchemy.ext.hybrid import hybrid_property
+
+from airflow import settings
+from airflow import models
+from airflow.utils.db import provide_session
+from airflow.utils.log.logging_mixin import LoggingMixin
+
+login_manager = flask_login.LoginManager()
+login_manager.login_view = 'airflow.login'  # Calls login() below
+login_manager.login_message = None
+
+log = LoggingMixin().log
+PY3 = version_info[0] == 3
+
+
+class AuthenticationError(Exception):
+    pass
+
+
+class PasswordUser(models.User):
+    _password = Column('password', String(255))
+
+    def __init__(self, user):
+        self.user = user
+
+    @hybrid_property
+    def password(self):
+        return self._password
+
+    @password.setter
+    def _set_password(self, plaintext):
+        self._password = generate_password_hash(plaintext, 12)
+        if PY3:
+            self._password = str(self._password, 'utf-8')
+
+    def authenticate(self, plaintext):
+        return check_password_hash(self._password, plaintext)
+
+    def is_active(self):
+        '''Required by flask_login'''
+        return True
+
+    def is_authenticated(self):
+        '''Required by flask_login'''
+        return True
+
+    def is_anonymous(self):
+        '''Required by flask_login'''
+        return False
+
+    def get_id(self):
+        '''Returns the current user id as required by flask_login'''
+        return str(self.id)
+
+    def data_profiling(self):
+        '''Provides access to data profiling tools'''
+        return True
+
+    def is_superuser(self):
+        '''Access all the things'''
+        return True
+
+
+@login_manager.user_loader
+@provide_session
+def load_user(userid, session=None):
+    log.debug("Loading user %s", userid)
+    if not userid or userid == 'None':
+        return None
+
+    user = session.query(models.User).filter(models.User.id == 
int(userid)).first()
+    return PasswordUser(user)
+
+
+def authenticate(session, username, password):
+    """
+    Authenticate a PasswordUser with the specified
+    username/password.
+
+    :param session: An active SQLAlchemy session
+    :param username: The username
+    :param password: The password
+
+    :raise AuthenticationError: if an error occurred
+    :return: a PasswordUser
+    """
+    if not username or not password:
+        raise AuthenticationError()
+
+    user = session.query(PasswordUser).filter(
+        PasswordUser.username == username).first()
+
+    if not user:
+        raise AuthenticationError()
+
+    if not user.authenticate(password):
+        raise AuthenticationError()
+
+    log.info("User %s successfully authenticated", username)
+    return user
+
+
+@provide_session
+def login(self, request, session=None):
+    if current_user.is_authenticated():
+        flash("You are already logged in")
+        return redirect(url_for('admin.index'))
+
+    username = None
+    password = None
+
+    form = LoginForm(request.form)
+
+    if request.method == 'POST' and form.validate():
+        username = request.form.get("username")
+        password = request.form.get("password")
+
+    try:
+        user = authenticate(session, username, password)
+        flask_login.login_user(user)
+
+        return redirect(request.args.get("next") or url_for("admin.index"))
+    except AuthenticationError:
+        flash("Incorrect login details")
+        return self.render('airflow/login.html',
+                           title="Airflow - Login",
+                           form=form)
+    finally:
+        session.commit()
+        session.close()
+
+
+class LoginForm(Form):
+    username = StringField('Username', [InputRequired()])
+    password = PasswordField('Password', [InputRequired()])
+
+
+def _unauthorized():
+    """
+    Indicate that authorization is required
+    :return:
+    """
+    return Response("Unauthorized", 401, {"WWW-Authenticate": "Basic"})
+
+
+def _forbidden():
+    return Response("Forbidden", 403)
+
+
+def init_app(app):
+    pass
+
+
+def requires_authentication(function):
+    @wraps(function)
+    def decorated(*args, **kwargs):
+        from flask import request
+
+        header = request.headers.get("Authorization")
+        if header:
+            userpass = ''.join(header.split()[1:])
+            username, password = 
base64.b64decode(userpass).decode("utf-8").split(":", 1)
+
+            session = settings.Session()
+            try:
+                authenticate(session, username, password)
+
+                response = function(*args, **kwargs)
+                response = make_response(response)
+                return response
+
+            except AuthenticationError:
+                return _forbidden()
+
+            finally:
+                session.commit()
+                session.close()
+        return _unauthorized()
+    return decorated

http://git-wip-us.apache.org/repos/asf/incubator-airflow/blob/7cba8333/tests/www/api/experimental/test_password_endpoints.py
----------------------------------------------------------------------
diff --git a/tests/www/api/experimental/test_password_endpoints.py 
b/tests/www/api/experimental/test_password_endpoints.py
index 2c2cc7f..1bf58fa 100644
--- a/tests/www/api/experimental/test_password_endpoints.py
+++ b/tests/www/api/experimental/test_password_endpoints.py
@@ -1,81 +1,81 @@
-# -*- coding: utf-8 -*-
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-import json
-import unittest
-
-from datetime import datetime
-
-from airflow import models
-from airflow import configuration
-from airflow.www import app as application
-from airflow.settings import Session
-from airflow.contrib.auth.backends.password_auth import PasswordUser
-
-try:
-    from ConfigParser import DuplicateSectionError
-except ImportError:
-    from configparser import DuplicateSectionError
-
-
-class ApiPasswordTests(unittest.TestCase):
-    def setUp(self):
-        configuration.load_test_config()
-        try:
-            configuration.conf.add_section("api")
-        except DuplicateSectionError:
-            pass
-
-        configuration.conf.set("api",
-                               "auth_backend",
-                               "airflow.contrib.auth.backends.password_auth")
-
-        self.app = application.create_app(testing=True)
-
-        session = Session()
-        user = models.User()
-        password_user = PasswordUser(user)
-        password_user.username = 'hello'
-        password_user.password = 'world'
-        session.add(password_user)
-        session.commit()
-        session.close()
-
-    def test_authorized(self):
-        with self.app.test_client() as c:
-            url_template = '/api/experimental/dags/{}/dag_runs'
-            response = c.post(
-                url_template.format('example_bash_operator'),
-                data=json.dumps(dict(run_id='my_run' + 
datetime.now().isoformat())),
-                content_type="application/json",
-                headers={'Authorization': 'Basic aGVsbG86d29ybGQ='}  # 
hello:world
-            )
-            self.assertEqual(200, response.status_code)
-
-    def test_unauthorized(self):
-        with self.app.test_client() as c:
-            url_template = '/api/experimental/dags/{}/dag_runs'
-            response = c.post(
-                url_template.format('example_bash_operator'),
-                data=json.dumps(dict(run_id='my_run' + 
datetime.now().isoformat())),
-                content_type="application/json"
-            )
-
-            self.assertEqual(401, response.status_code)
-
-    def tearDown(self):
-        session = Session()
-        session.query(models.User).delete()
-        session.commit()
-        session.close()
+# -*- coding: utf-8 -*-
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import json
+import unittest
+
+from datetime import datetime
+
+from airflow import models
+from airflow import configuration
+from airflow.www import app as application
+from airflow.settings import Session
+from airflow.contrib.auth.backends.password_auth import PasswordUser
+
+try:
+    from ConfigParser import DuplicateSectionError
+except ImportError:
+    from configparser import DuplicateSectionError
+
+
+class ApiPasswordTests(unittest.TestCase):
+    def setUp(self):
+        configuration.load_test_config()
+        try:
+            configuration.conf.add_section("api")
+        except DuplicateSectionError:
+            pass
+
+        configuration.conf.set("api",
+                               "auth_backend",
+                               "airflow.contrib.auth.backends.password_auth")
+
+        self.app = application.create_app(testing=True)
+
+        session = Session()
+        user = models.User()
+        password_user = PasswordUser(user)
+        password_user.username = 'hello'
+        password_user.password = 'world'
+        session.add(password_user)
+        session.commit()
+        session.close()
+
+    def test_authorized(self):
+        with self.app.test_client() as c:
+            url_template = '/api/experimental/dags/{}/dag_runs'
+            response = c.post(
+                url_template.format('example_bash_operator'),
+                data=json.dumps(dict(run_id='my_run' + 
datetime.now().isoformat())),
+                content_type="application/json",
+                headers={'Authorization': 'Basic aGVsbG86d29ybGQ='}  # 
hello:world
+            )
+            self.assertEqual(200, response.status_code)
+
+    def test_unauthorized(self):
+        with self.app.test_client() as c:
+            url_template = '/api/experimental/dags/{}/dag_runs'
+            response = c.post(
+                url_template.format('example_bash_operator'),
+                data=json.dumps(dict(run_id='my_run' + 
datetime.now().isoformat())),
+                content_type="application/json"
+            )
+
+            self.assertEqual(401, response.status_code)
+
+    def tearDown(self):
+        session = Session()
+        session.query(models.User).delete()
+        session.commit()
+        session.close()

Reply via email to