Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sqlalchemy scope fix #46

Merged
merged 4 commits into from
Jun 1, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/configuration.rst
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ Services and collections can be created with supplied CLI tools. It is also poss

Step 1
------
We will need to create YAML files with services and collections configurations. You can create your own file or use examples from OpenTAXII `git repo <https://github.com/eclecticiq/OpenTAXII>`_:
We will need to create YAML files with services and collections configurations. You can create your own file or use examples from `OpenTAXII git repo <https://github.com/eclecticiq/OpenTAXII>`_:

* `examples/services.yml <https://raw.githubusercontent.com/eclecticiq/OpenTAXII/master/examples/services.yml>`_

Expand Down
13 changes: 7 additions & 6 deletions examples/hooks.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,19 @@


def post_create_content_block(manager, content_block, collection_ids,
service_id):
print 'Content block id=%s (collections=%s, service_id=%s) was created' % (
content_block.id, ', '.join(map(str, collection_ids)), service_id)
service_id):
print('Content block id={} (collections={}, service_id={}) was created'
.format(content_block.id, ', '.join(map(str, collection_ids)),
service_id))


def post_create_inbox_message(manager, inbox_message):
print 'Inbox message id=%s was created' % inbox_message.id
print('Inbox message id={} was created'.format(inbox_message.id))


def post_create_subscription(manager, subscription):
print 'Subscription id=%s (service_id=%s) was created' % (subscription.id,
subscription.service_id)
print('Subscription id={} (service_id={}) was created'
.format(subscription.id, subscription.service_id))


CONTENT_BLOCK_CREATED.connect(post_create_content_block)
Expand Down
69 changes: 29 additions & 40 deletions opentaxii/auth/sqldb/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,53 +3,55 @@

from datetime import datetime, timedelta

from sqlalchemy import orm, engine
from sqlalchemy.orm import exc

from opentaxii.auth import OpenTAXIIAuthAPI
from opentaxii.entities import Account
from opentaxii.entities import Account as AccountEntity
from opentaxii.sqldb_helper import SQLAlchemyDB

from . import models
from .models import Base, Account

__all__ = ['SQLDatabaseAPI']


TOKEN_TTL = 60 # min
TOKEN_TTL = 60 # min

log = structlog.getLogger(__name__)


class SQLDatabaseAPI(OpenTAXIIAuthAPI):
"""Naive SQL database implementation of OpenTAXII Auth API.

def __init__(self, db_connection, create_tables=False, secret=None):

self.engine = engine.create_engine(db_connection, convert_unicode=True)
Implementation will work with any DB supported by SQLAlchemy package.

self.Session = orm.scoped_session(orm.sessionmaker(autocommit=False,
autoflush=True, bind=self.engine))
:param str db_connection: a string that indicates database dialect and
connection arguments that will be passed directly
to :func:`~sqlalchemy.engine.create_engine` method.

attach_all(self, models)
:param bool create_tables=False: if True, tables will be created in the DB.
"""

self.Base.query = self.Session.query_property()
def __init__(self, db_connection, create_tables=False, secret=None):

self.db = SQLAlchemyDB(
db_connection, Base, session_options={
'autocommit': False, 'autoflush': True,
})
if create_tables:
self.create_tables()
self.db.create_all_tables()

if not secret:
raise ValueError('Secret is not defined for %s.%s' % (
self.__module__, self.__class__.__name__))

self.secret = secret


def create_tables(self):
self.Base.metadata.create_all(bind=self.engine)

def init_app(self, app):
self.db.init_app(app)

def authenticate(self, username, password):

try:
account = self.Account.query.filter_by(username=username).one()
account = Account.query.filter_by(username=username).one()
except exc.NoResultFound:
return

Expand All @@ -58,38 +60,35 @@ def authenticate(self, username, password):

return self._generate_token(account.id, ttl=TOKEN_TTL)


def get_account(self, token):

account_id = self._get_account_id(token)

if not account_id:
return

account = self.Account.query.get(account_id)
account = Account.query.get(account_id)

if not account:
return

return Account(id=account.id)
return AccountEntity(id=account.id)

def create_account(self, username, password):

account = self.Account(username=username)
account = Account(username=username)
account.set_password(password)

session = self.Session()
session.add(account)
session.commit()
self.db.session.add(account)
self.db.session.commit()

return Account(id=account.id)
return AccountEntity(id=account.id)

def _generate_token(self, account_id, ttl=TOKEN_TTL):

exp = datetime.utcnow() + timedelta(minutes=ttl)

return jwt.encode({'account_id' : account_id, 'exp' : exp}, self.secret)

return jwt.encode(
{'account_id': account_id, 'exp': exp},
self.secret)

def _get_account_id(self, token):
try:
Expand All @@ -102,13 +101,3 @@ def _get_account_id(self, token):
return

return payload.get('account_id')



def attach_all(obj, module):
for key in module.__all__:
if not hasattr(obj, key):
setattr(obj, key, getattr(module, key))
return obj


7 changes: 1 addition & 6 deletions opentaxii/auth/sqldb/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,7 @@ class Account(Base):
password_hash = Column(String(MAX_STR_LEN))

def set_password(self, password):
if isinstance(password, unicode):
password = password.encode('utf-8')
self.password_hash = generate_password_hash(password)

def is_password_valid(self, password):
if isinstance(password, unicode):
password = password.encode('utf-8')
password_hash = self.password_hash.encode('utf-8')
return check_password_hash(password_hash, password)
return check_password_hash(self.password_hash, password)
1 change: 0 additions & 1 deletion opentaxii/cli/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +0,0 @@

16 changes: 10 additions & 6 deletions opentaxii/cli/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,22 +14,26 @@

def get_parser():
parser = argparse.ArgumentParser(
description = "Create Account via OpenTAXII Auth API",
formatter_class = argparse.ArgumentDefaultsHelpFormatter
description="Create Account via OpenTAXII Auth API",
formatter_class=argparse.ArgumentDefaultsHelpFormatter
)
return parser


def create_account():

parser = get_parser()
parser.add_argument("-u", "--username", dest="username", help="Username for the new account", required=True)
parser.add_argument("-p", "--password", dest="password", help="Password for the new account", required=True)
parser.add_argument(
"-u", "--username", dest="username",
help="Username for the new account", required=True)

parser.add_argument(
"-p", "--password", dest="password",
help="Password for the new account", required=True)

args = parser.parse_args()

server = TAXIIServer(config)
token = server.auth.create_account(args.username, args.password)

log.info("Account created", token=token)

log.info("Account created", username=args.username, token=token)
24 changes: 14 additions & 10 deletions opentaxii/cli/persistence.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@

def get_parser():
parser = argparse.ArgumentParser(
description = "Create services via OpenTAXII Auth API",
formatter_class = argparse.ArgumentDefaultsHelpFormatter
description="Create services via OpenTAXII Auth API",
formatter_class=argparse.ArgumentDefaultsHelpFormatter
)
return parser

Expand All @@ -25,8 +25,9 @@ def create_services():

parser = get_parser()

parser.add_argument("-c", "--services-config", dest="config",
help="YAML file with services configuration", required=True)
parser.add_argument(
"-c", "--services-config", dest="config",
help="YAML file with services configuration", required=True)

args = parser.parse_args()

Expand All @@ -42,8 +43,9 @@ def create_collections():

parser = get_parser()

parser.add_argument("-c", "--collections-config", dest="config",
help="YAML file with collections configuration", required=True)
parser.add_argument(
"-c", "--collections-config", dest="config",
help="YAML file with collections configuration", required=True)

args = parser.parse_args()
server = TAXIIServer(config)
Expand All @@ -65,15 +67,17 @@ def create_collections():
break

if existing:
log.warning("collection.skipped.already_exists",
collection_name=collection['name'],
existing_id=existing.id)
log.warning(
"collection.skipped.already_exists",
collection_name=collection['name'],
existing_id=existing.id)
continue

entity = CollectionEntity(**collection)

c = server.persistence.create_collection(entity)
server.persistence.attach_collection_to_services(c.id, service_ids=service_ids)
server.persistence.attach_collection_to_services(
c.id, service_ids=service_ids)
created += 1

log.info("Collections created", count=created)
5 changes: 3 additions & 2 deletions opentaxii/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ def __init__(self, optional_env_var=CONFIG_ENV_VAR, extra_configs=None):
if env_var_path:
config_paths.append(env_var_path)

options = anyconfig.load(config_paths, ac_parser='yaml',
ignore_missing=False, ac_merge=anyconfig.MS_REPLACE)
options = anyconfig.load(
config_paths, ac_parser='yaml',
ignore_missing=False, ac_merge=anyconfig.MS_REPLACE)

self.update(options)
1 change: 0 additions & 1 deletion opentaxii/entities.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,3 @@ def __init__(self, id, **details):

self.id = id
self.details = details

1 change: 1 addition & 0 deletions opentaxii/exceptions.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@

from .taxii.exceptions import UnauthorizedStatus


class UnauthorizedException(UnauthorizedStatus):
pass

Expand Down
3 changes: 1 addition & 2 deletions opentaxii/http.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,8 @@
from .utils import configure_logging

config = ServerConfig()
configure_logging(config.get('logging', {'' : 'info'}))
configure_logging(config.get('logging', {'': 'info'}))

server = TAXIIServer(config)
app = create_app(server)
app.debug = False

1 change: 1 addition & 0 deletions opentaxii/local.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@
context = Local()
local_manager = LocalManager([context])


def release_context():
local_manager.cleanup()
8 changes: 5 additions & 3 deletions opentaxii/management.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

management = Blueprint('management', __name__)


@management.route('/auth', methods=['POST'])
def auth():
data = request.get_json() or request.form
Expand All @@ -12,12 +13,13 @@ def auth():
if not username or not password:
return 'Both username and password are required', 400

token = current_app.taxii.auth.authenticate(username, password)
token = current_app.taxii_server.auth.authenticate(username, password)

if not token:
abort(401)

return jsonify(token=token)

return jsonify(token=token.decode('utf-8'))


@management.route('/health', methods=['GET'])
def health():
Expand Down
Loading