Skip to content
Open
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 .github/workflows/developer-connect-api-ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,6 @@ jobs:
developer-connect-api-ci:
uses: bcgov/bcregistry-sre/.github/workflows/backend-ci.yaml@main
with:
app_name: developer-connect-api"
app_name: developer-connect-api
working_directory: "./api"
codecov_flag: "devloperconnectapi"
2,897 changes: 1,963 additions & 934 deletions api/poetry.lock

Large diffs are not rendered by default.

15 changes: 8 additions & 7 deletions api/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,20 @@ description = ""
authors = ["thorwolpert <thor@wolpert.ca>"]
license = "BSD 3-Clause"
readme = "README.md"
packages = [{include = "developer-connect-api", from = "src"}]
packages = [{include = "developer_connect_api", from = "src"}]

[tool.poetry.dependencies]
python = "^3.12.4"
flask = "^1.1.4"
launchdarkly-server-sdk = "^8.3.0"
python = ">=3.12.4,<3.14"
flask = ">=3.0.2"
launchdarkly-server-sdk = ">=8.2.1"
python-dotenv = "^1.0.1"
sentry-sdk = "^2.0.0"
flask-babel = "2.0.0"
flask-jwt-oidc = "^0.7.0"
flask-babel = "^4.0.0"
flask-jwt-oidc = ">=0.7.0"
gunicorn = "^22.0.0"
sbc-common-components = {git = "https://github.com/bcgov/sbc-common-components.git", rev = "master", subdirectory = "python"}
auth-api = {git = "https://github.com/bcgov/sbc-auth.git", rev = "c286045eb2cf9761cd57b59aa4c6e7b3146ea36c", subdirectory = "auth-api"}
auth-api = {git = "https://github.com/bcgov/sbc-auth.git", rev = "2768c4cad589438de58f6d8669fd90952b83c938", subdirectory = "auth-api"}
typing-extensions = ">=4.12.2"

[tool.poetry.group.test.dependencies]
freezegun = "^1.5.1"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
from flask import has_app_context
from flask import Flask

import developer-connect-api
import developer_connect_api


class Flags:
Expand Down Expand Up @@ -115,9 +115,9 @@ def get_anonymous_user():
return {"key": "anonymous"}

@staticmethod
def flag_user(user: developer-connect-api.models.User, account_id: int = None):
def flag_user(user: developer_connect_api.models.User, account_id: int = None):
"""Convert User into a Flag user dict."""
if not isinstance(user, developer-connect-api.models.User):
if not isinstance(user, developer_connect_api.models.User):
return None

_user = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@
from flask_cors import cross_origin

from http import HTTPStatus
from developer-connect-api.common.auth import jwt as _jwt
from developer_connect_api.common.auth import jwt as _jwt
from auth_api.exceptions import BusinessException
from auth_api.schemas import utils as schema_utils
from developer-connect-api.services.api_gateway import ApiGateway as ApiGatewayService
from developer_connect_api.services.api_gateway import ApiGateway as ApiGatewayService
from auth_api.utils.roles import Role

bp = Blueprint("KEYS", __name__, url_prefix=f"/v1/orgs/<int:org_id>/api-keys")
Expand Down
147 changes: 4 additions & 143 deletions api/tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,91 +12,15 @@
# See the License for the specific language governing permissions and
# limitations under the License.
"""Common setup and fixtures for the pytest suite used by this service."""
import contextlib
import datetime
import time
from contextlib import contextmanager, suppress
from typing import Final
from contextlib import contextmanager

import psycopg2
import pytest
import sqlalchemy
from flask_migrate import Migrate, upgrade
from ldclient.integrations.test_data import TestData
from sqlalchemy import event, text

from developer-connect-api import create_app
from developer-connect-api import jwt as _jwt
from developer-connect-api.models import db as _db
from developer-connect-api.config import Testing

def create_test_db(user: str = None,
password: str = None,
database: str = None,
host: str = "localhost",
port: int = 1521,
database_uri: str = None) -> bool:
"""Create the database in our .devcontainer launched postgres DB.

Parameters
------------
user: str
A datbase user that has create database privledges
password: str
The users password
database: str
The name of the database to create
host: str, Optional
The network name of the server
port: int, Optional
The numeric port number
Return
-----------
: bool
If the create database succeeded.
"""
if database_uri:
DATABASE_URI = database_uri
else:
DATABASE_URI = f"postgresql://{user}:{password}@{host}:{port}/{user}"

DATABASE_URI = DATABASE_URI[:DATABASE_URI.rfind("/")] + '/postgres'
from developer_connect_api import create_app
from developer_connect_api import jwt as _jwt
from developer_connect_api.config import Testing

try:
with sqlalchemy.create_engine(DATABASE_URI, isolation_level="AUTOCOMMIT").connect() as conn:
conn.execute(text(f"CREATE DATABASE {database}"))

return True
except sqlalchemy.exc.ProgrammingError as err:
print(err) # used in the test suite, so on failure print something
return False

def drop_test_db(user: str = None,
password: str = None,
database: str = None,
host: str = "localhost",
port: int = 1521,
database_uri: str = None) -> bool:
"""Delete the database in our .devcontainer launched postgres DB."""
if database_uri:
DATABASE_URI = database_uri
else:
DATABASE_URI = f"postgresql://{user}:{password}@{host}:{port}/{user}"

DATABASE_URI = DATABASE_URI[:DATABASE_URI.rfind("/")] + '/postgres'

close_all = f"""
SELECT pg_terminate_backend(pg_stat_activity.pid)
FROM pg_stat_activity
WHERE pg_stat_activity.datname = '{database}'
AND pid <> pg_backend_pid();
"""
with contextlib.suppress(sqlalchemy.exc.ProgrammingError,
psycopg2.OperationalError,
Exception):
with sqlalchemy.create_engine(DATABASE_URI, isolation_level="AUTOCOMMIT").connect() as conn:
conn.execute(text(close_all))
conn.execute(text(f"DROP DATABASE {database}"))

@contextmanager
def not_raises(exception):
Expand Down Expand Up @@ -144,66 +68,3 @@ def client_ctx(app): # pylint: disable=redefined-outer-name
yield _client


@pytest.fixture(scope='session')
def db(app): # pylint: disable=redefined-outer-name, invalid-name
"""Return a session-wide initialised database.

Drops all existing tables - Meta follows Postgres FKs
"""
with app.app_context():
create_test_db(database=app.config.get('DATABASE_TEST_NAME'),
database_uri=app.config.get('SQLALCHEMY_DATABASE_URI'))

sess = _db.session()
sess.execute(text("SET TIME ZONE 'UTC';"))

migrate = Migrate(app,
_db,
**{'dialect_name': 'postgres'})
upgrade()

yield _db

drop_test_db(database=app.config.get('DATABASE_TEST_NAME'),
database_uri=app.config.get('SQLALCHEMY_DATABASE_URI'))


@pytest.fixture(scope='function')
def session(app, db): # pylint: disable=redefined-outer-name, invalid-name
"""Return a function-scoped session."""
with app.app_context():
conn = db.engine.connect()
txn = conn.begin()

try:
options = dict(bind=conn, binds={})
# sess = db.create_scoped_session(options=options)
sess = db._make_scoped_session(options=options)
except Exception as err:
print(err)
print('done')

# establish a SAVEPOINT just before beginning the test
# (http://docs.sqlalchemy.org/en/latest/orm/session_transaction.html#using-savepoint)
sess.begin_nested()

@event.listens_for(sess(), 'after_transaction_end')
def restart_savepoint(sess2, trans): # pylint: disable=unused-variable
# Detecting whether this is indeed the nested transaction of the test
if trans.nested and not trans._parent.nested: # pylint: disable=protected-access
# Handle where test DOESN'T session.commit(),
sess2.expire_all()
sess.begin_nested()

db.session = sess

sql = text('select 1')
sess.execute(sql)

yield sess

# Cleanup
sess.remove()
# This instruction rollsback any commit that were executed in the tests.
txn.rollback()
conn.close()
2 changes: 1 addition & 1 deletion api/wsgi.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"""
import os

from developer-connect-api import create_app
from developer_connect_api import create_app

app = create_app() # pylint: disable=invalid-name

Expand Down
Loading