diff options
-rw-r--r-- | .pylintrc | 10 | ||||
-rw-r--r-- | README.md | 2 | ||||
-rw-r--r-- | gn_auth/__init__.py | 11 | ||||
-rw-r--r-- | gn_auth/auth/authorisation/data/genotypes.py | 2 | ||||
-rw-r--r-- | gn_auth/auth/authorisation/data/mrna.py | 2 | ||||
-rw-r--r-- | gn_auth/auth/authorisation/data/phenotypes.py | 2 | ||||
-rw-r--r-- | gn_auth/auth/authorisation/groups/data.py | 2 | ||||
-rw-r--r-- | gn_auth/auth/authorisation/resources/views.py | 2 | ||||
-rw-r--r-- | gn_auth/auth/db/__init__.py | 1 | ||||
-rw-r--r-- | gn_auth/auth/db/mariadb.py | 14 | ||||
-rw-r--r-- | gn_auth/auth/db/redis.py | 22 | ||||
-rw-r--r-- | gn_auth/auth/db/sqlite3.py | 2 | ||||
-rw-r--r-- | gn_auth/commands.py | 2 | ||||
-rw-r--r-- | scripts/migrate_existing_data.py | 2 |
14 files changed, 63 insertions, 13 deletions
diff --git a/.pylintrc b/.pylintrc new file mode 100644 index 0000000..2753c79 --- /dev/null +++ b/.pylintrc @@ -0,0 +1,10 @@ +[SIMILARITIES] + +ignore-imports=yes + +[MESSAGES CONTROL] + +disable= + fixme, + duplicate-code, + no-else-return
\ No newline at end of file @@ -10,7 +10,7 @@ used across the entire suite of the GeneNetwork services. ### Linting ```bash -pylint *py tests gn3 scripts +pylint *py tests gn_auth scripts ``` ### Type-Checking diff --git a/gn_auth/__init__.py b/gn_auth/__init__.py index 7d9228d..9b0264c 100644 --- a/gn_auth/__init__.py +++ b/gn_auth/__init__.py @@ -1,16 +1,19 @@ +"""Application initialisation module.""" + import os import sys import logging +from typing import Optional from flask import Flask -from . import settings - from gn_auth.auth import oauth2 from gn_auth.misc_views import misc from gn_auth.auth.authentication.oauth2.server import setup_oauth2_server +from . import settings + class ConfigurationError(Exception): """Raised in case of a configuration error.""" @@ -48,14 +51,14 @@ def setup_logging_handlers(app: Flask) -> None: root_logger.addHandler(stderr_handler) root_logger.setLevel(app.config["LOGLEVEL"]) -def create_app(config: dict = {}) -> Flask: +def create_app(config: Optional[dict] = None) -> Flask: """Create and return a new flask application.""" app = Flask(__name__) # ====== Setup configuration ====== app.config.from_object(settings) # Default settings # Override defaults with startup settings - app.config.update(config) + app.config.update(config or {}) # Override app settings with site-local settings if "GN_AUTH_CONF" in os.environ: app.config.from_envvar("GN_AUTH_CONF") diff --git a/gn_auth/auth/authorisation/data/genotypes.py b/gn_auth/auth/authorisation/data/genotypes.py index 61963a6..f5cf11c 100644 --- a/gn_auth/auth/authorisation/data/genotypes.py +++ b/gn_auth/auth/authorisation/data/genotypes.py @@ -4,7 +4,7 @@ from typing import Iterable from MySQLdb.cursors import DictCursor -import gn_auth.auth.db as authdb +import gn_auth.auth.db.sqlite3 as authdb import gn_auth.auth.db.mariadb as gn3db from gn_auth.auth.dictify import dictify from gn_auth.auth.authorisation.checks import authorised_p diff --git a/gn_auth/auth/authorisation/data/mrna.py b/gn_auth/auth/authorisation/data/mrna.py index 79ea7c0..b80ffe5 100644 --- a/gn_auth/auth/authorisation/data/mrna.py +++ b/gn_auth/auth/authorisation/data/mrna.py @@ -3,7 +3,7 @@ import uuid from typing import Iterable from MySQLdb.cursors import DictCursor -import gn_auth.auth.db as authdb +import gn_auth.auth.db.sqlite3 as authdb import gn_auth.auth.db.mariadb as gn3db from gn_auth.auth.dictify import dictify from gn_auth.auth.authorisation.checks import authorised_p diff --git a/gn_auth/auth/authorisation/data/phenotypes.py b/gn_auth/auth/authorisation/data/phenotypes.py index d3cc33a..0220201 100644 --- a/gn_auth/auth/authorisation/data/phenotypes.py +++ b/gn_auth/auth/authorisation/data/phenotypes.py @@ -4,7 +4,7 @@ from typing import Any, Iterable from MySQLdb.cursors import DictCursor -import gn_auth.auth.db as authdb +import gn_auth.auth.db.sqlite3 as authdb import gn_auth.auth.db.mariadb as gn3db from gn_auth.auth.dictify import dictify from gn_auth.auth.authorisation.checks import authorised_p diff --git a/gn_auth/auth/authorisation/groups/data.py b/gn_auth/auth/authorisation/groups/data.py index 2d9ddb5..a73ae3d 100644 --- a/gn_auth/auth/authorisation/groups/data.py +++ b/gn_auth/auth/authorisation/groups/data.py @@ -2,7 +2,7 @@ from MySQLdb.cursors import DictCursor from gn_auth.auth.db import mariadb as gn3db -from gn_auth.auth.db import sqlite3 as authdb +import gn_auth.auth.db.sqlite3 as authdb from gn_auth.auth.authorisation.groups import Group from gn_auth.auth.authorisation.checks import authorised_p from gn_auth.auth.authorisation.errors import NotFoundError diff --git a/gn_auth/auth/authorisation/resources/views.py b/gn_auth/auth/authorisation/resources/views.py index 157d5a3..e7af9b9 100644 --- a/gn_auth/auth/authorisation/resources/views.py +++ b/gn_auth/auth/authorisation/resources/views.py @@ -6,6 +6,7 @@ from functools import reduce from flask import request, jsonify, Response, Blueprint, current_app as app +from gn_auth.auth.db import sqlite3 as db from gn_auth.auth.db.sqlite3 import with_db_connection from .checks import authorised_for @@ -19,7 +20,6 @@ from ..roles import Role from ..errors import InvalidData, InconsistencyError, AuthorisationError from ..groups.models import Group, GroupRole, group_role_by_id -from ... import db from ...dictify import dictify from ...authentication.oauth2.resource_server import require_oauth from ...authentication.users import User, user_by_id, user_by_email diff --git a/gn_auth/auth/db/__init__.py b/gn_auth/auth/db/__init__.py index eab58ef..7bdb38a 100644 --- a/gn_auth/auth/db/__init__.py +++ b/gn_auth/auth/db/__init__.py @@ -1 +1,2 @@ +"""Unified database connections module.""" from .protocols import DbCursor, DbConnection diff --git a/gn_auth/auth/db/mariadb.py b/gn_auth/auth/db/mariadb.py index a934fd9..69c1d8e 100644 --- a/gn_auth/auth/db/mariadb.py +++ b/gn_auth/auth/db/mariadb.py @@ -1,12 +1,22 @@ """Connections to MariaDB""" +import logging import traceback import contextlib -from typing import Iterator +from urllib.parse import urlparse +from typing import Tuple, Iterator import MySQLdb as mdb from .protocols import DbConnection +def parse_db_url(sql_uri: str) -> Tuple: + """Parse SQL_URI env variable note:there is a default value for SQL_URI so a + tuple result is always expected""" + parsed_db = urlparse(sql_uri) + return ( + parsed_db.hostname, parsed_db.username, parsed_db.password, + parsed_db.path[1:], parsed_db.port) + @contextlib.contextmanager def database_connection(sql_uri) -> Iterator[DbConnection]: """Connect to MySQL database.""" @@ -18,7 +28,7 @@ def database_connection(sql_uri) -> Iterator[DbConnection]: port=port or 3306) try: yield connection - except Exception as _exc: # TODO: Make the Exception class less general + except mdb.Error as _mdb_err: logging.debug(traceback.format_exc()) connection.rollback() finally: diff --git a/gn_auth/auth/db/redis.py b/gn_auth/auth/db/redis.py new file mode 100644 index 0000000..fdf1d6f --- /dev/null +++ b/gn_auth/auth/db/redis.py @@ -0,0 +1,22 @@ +"""Connections for Redis.""" +import logging +import traceback +import contextlib +from typing import Iterator + +from redis import Redis, RedisError, ConnectionError as RedisConnectionError + +@contextlib.contextmanager +def connection(redis_uri) -> Iterator[Redis]: + """Connection to redis""" + rconn = Redis.from_url(redis_uri, decode_responses=True) + try: + if not rconn.ping(): + raise RedisConnectionError("Could not connect to Redis.") + yield rconn + except RedisError as _rerr: + logging.debug(traceback.format_exc()) + raise + finally: + rconn.disconnect() + rconn.close() diff --git a/gn_auth/auth/db/sqlite3.py b/gn_auth/auth/db/sqlite3.py index 3d94832..be9eb2f 100644 --- a/gn_auth/auth/db/sqlite3.py +++ b/gn_auth/auth/db/sqlite3.py @@ -6,6 +6,8 @@ from typing import Any, Callable, Iterator import traceback +from flask import current_app + from .protocols import DbCursor, DbConnection @contextlib.contextmanager diff --git a/gn_auth/commands.py b/gn_auth/commands.py index d6f6f56..cc00413 100644 --- a/gn_auth/commands.py +++ b/gn_auth/commands.py @@ -10,6 +10,8 @@ from typing import Dict, Optional, Tuple, Union, Sequence from redis.client import Redis +from gn_auth.auth.db.redis import RedisConnectionError + def queue_cmd(conn: Redis, job_queue: str, cmd: Union[str, Sequence[str]], diff --git a/scripts/migrate_existing_data.py b/scripts/migrate_existing_data.py index 4452f41..7cd6086 100644 --- a/scripts/migrate_existing_data.py +++ b/scripts/migrate_existing_data.py @@ -14,7 +14,7 @@ from MySQLdb.cursors import DictCursor from gn_auth.auth.db import mariadb as biodb -from gn_auth.auth.db import sqlite3 as authdb +import gn_auth.auth.db.sqlite3 as authdb from gn_auth.auth.authentication.users import User from gn_auth.auth.authorisation.groups.models import Group, save_group from gn_auth.auth.authorisation.roles.models import ( |