Skip to content

Commit

Permalink
Making login module generic / overridable
Browse files Browse the repository at this point in the history
  • Loading branch information
mistercrunch committed Mar 30, 2015
1 parent e3521c1 commit 4518dcb
Show file tree
Hide file tree
Showing 10 changed files with 365 additions and 264 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
*.pyc
airflow/www/static/coverage/
.ipynb*
docs/_*
airflow.db
Expand All @@ -16,3 +17,4 @@ secrets.py
*.egg-info
*.bkp
.DS_Store
airflow_login.py
13 changes: 2 additions & 11 deletions TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,31 +4,22 @@ TODO
* Backfill wizard

#### unittests
* Increase coverage, now 80ish%
* Increase coverage, now 85ish%

#### Command line
* `airflow task_state dag_id task_id YYYY-MM-DD`

#### More Operators!
* Sandbox the BashOperator
* S3Sensor
* BaseDataTransferOperator
* File2MySqlOperator
* DagTaskSensor for cross dag dependencies
* PIG

#### Frontend
*

#### Backend
* Make authentication universal
* Callbacks
* Master auto dag refresh at time intervals
* Prevent timezone chagne on import
* Add decorator to timeout imports on master process [lib](https://github.com/pnpnpn/timeout-decorator)
* Make authentication universal

#### Misc
* Write an hypervisor, looks for dead jobs without a heartbeat and kills

#### Wishlist
* Support for cron like synthax (0 * * * ) using croniter library
19 changes: 17 additions & 2 deletions airflow/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,18 @@
from models import DAG

__version__ = "0.4.3"

'''
Authentication is implemented using flask_login and different environments can
implement their own login mechanisms by providing an `airflow_login` module
in their PYTHONPATH. airflow_login should be based off the
`airflow.www.login`
'''
try:
# Environment specific login
import airflow_login
login = airflow_login
except ImportError:
# Default login, no real authentication
from airflow import default_login
login = default_login

from models import DAG
72 changes: 72 additions & 0 deletions airflow/default_login.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
'''
Override this file to handle your authenticatin / login.
Copy and alter this file and put in your PYTHONPATH as airflow_login.py,
the new module will override this one.
'''

import flask_login
from flask_login import login_required, current_user, logout_user

from flask import url_for, redirect

from airflow import settings
from airflow import models

DEFAULT_USERNAME = 'airflow'

login_manager = flask_login.LoginManager()
login_manager.login_view = 'airflow.login' # Calls login() bellow
login_manager.login_message = None


class User(models.BaseUser):

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 data_profiling(self):
'''Provides access to data profiling tools'''
return True

def is_superuser(self):
'''Access all the things'''
return True

models.User = User # hack!


@login_manager.user_loader
def load_user(userid):
session = settings.Session()
user = session.query(User).filter(User.id == userid).first()
session.expunge_all()
session.commit()
session.close()
return user


def login(self, request):
session = settings.Session()
user = session.query(User).filter(
User.username == DEFAULT_USERNAME).first()
if not user:
user = User(
username=DEFAULT_USERNAME,
has_access=True,
is_superuser=True)
session.merge(user)
session.expunge_all()
session.commit()
session.close()
flask_login.login_user(user)
return redirect(request.args.get("next") or url_for("index"))
25 changes: 8 additions & 17 deletions airflow/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -183,34 +183,19 @@ def paused_dags(self):
return dag_ids


class User(Base):
"""
Eventually should be used for security purposes
"""
class BaseUser(Base):
__tablename__ = "user"

id = Column(Integer, primary_key=True)
username = Column(String(ID_LEN), unique=True)
email = Column(String(500))

def __init__(self, username=None, email=None):
self.username = username
self.email = email

def __repr__(self):
return self.username

def get_id(self):
return unicode(self.id)

def is_active(self):
return True

def is_authenticated(self):
return True

def is_anonymous(self):
return False


class Connection(Base):
"""
Expand Down Expand Up @@ -1507,6 +1492,9 @@ class Chart(Base):
iteration_no = Column(Integer, default=0)
last_modified = Column(DateTime, default=datetime.now())

def __repr__(self):
return self.label


class KnownEventType(Base):
__tablename__ = "known_event_type"
Expand Down Expand Up @@ -1534,3 +1522,6 @@ class KnownEvent(Base):
cascade=False,
cascade_backrefs=False, backref='known_events')
description = Column(Text)

def __repr__(self):
return self.label
1 change: 1 addition & 0 deletions airflow/operators/email_operator.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
class EmailOperator(BaseOperator):

template_fields = ('subject', 'html_content')
template_ext = ('.html',)
ui_color = '#e6faf9'

__mapper_args__ = {
Expand Down
Loading

0 comments on commit 4518dcb

Please sign in to comment.