Skip to content
This repository has been archived by the owner on Jul 10, 2021. It is now read-only.

Commit

Permalink
Merge branch 'master' of github.com:fvalverd/AutoApi
Browse files Browse the repository at this point in the history
  • Loading branch information
fvalverd committed May 17, 2020
2 parents 964668b + 2ebbd90 commit 49b2ef0
Show file tree
Hide file tree
Showing 20 changed files with 263 additions and 142 deletions.
30 changes: 30 additions & 0 deletions .github/workflows/docker.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
name: docker

on:
release:
types: [published]

jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Push to Docker Hub
uses: docker/build-push-action@v1
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_ACCESS_TOKEN }}
repository: ${{ secrets.DOCKER_USERNAME }}/autoapi
tag_with_ref: true
push: ${{ startsWith(github.ref, 'refs/tags/') }}
target: runtime-autoapi
- name: Push to GitHub Packages
uses: docker/build-push-action@v1
with:
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
registry: docker.pkg.github.com
repository: ${{ github.actor }}/autoapi/autoapi
push: ${{ startsWith(github.ref, 'refs/tags/') }}
tag_with_ref: true
target: runtime-autoapi
28 changes: 0 additions & 28 deletions .github/workflows/publish.yaml

This file was deleted.

26 changes: 26 additions & 0 deletions .github/workflows/pypi.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
name: pypi

on:
release:
types: [created]

jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up Python
uses: actions/setup-python@v1
with:
python-version: '3.x'
- name: Install dependencies
run: |
python -m pip install -U -r requirements-tools.txt
python -m pip install twine
- name: Build and publish
env:
TWINE_USERNAME: ${{ secrets.PYPI_USERNAME }}
TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }}
run: |
python setup.py sdist bdist_wheel
twine upload dist/*
4 changes: 3 additions & 1 deletion .github/workflows/tests.yaml
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
name: tests

on:
push:
branches: [ master ]
pull_request:
branches: [ master ]

jobs:
tests:
strategy:
Expand Down Expand Up @@ -43,7 +45,7 @@ jobs:
# docker run -d -p ${{ env.MONGO_PORT_AUTH }}:27017 -v $MONGO_AUTH_DIR:C:\db mongo:latest mongod --auth --bind_ip_all --dbpath=C:\db
# if: ${{ matrix.platform == 'windows-latest' }}
- name: Set MongoDB root user as Auto-Api admin
run: python setup_admin_user.py
run: python -m auto_api update-admin --port ${{ env.MONGO_PORT_AUTH }}
- name: Run unit, integration and functional tests
run: python -m pytest -v
- name: Coveralls
Expand Down
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ install:
- docker run -d -p $MONGO_PORT:27017 mongo:$MONGO_VERSION mongod --bind_ip_all
before_script:
- docker run -d -p $MONGO_PORT_AUTH:27017 -e MONGO_INITDB_ROOT_USERNAME=$MONGO_ADMIN -e MONGO_INITDB_ROOT_PASSWORD=$MONGO_ADMIN_PASS mongo:$MONGO_VERSION mongod --auth --bind_ip_all
- python setup_admin_user.py
- python -m auto_api update-admin --port $MONGO_PORT_AUTH
script:
- python -m pytest -v
# after_script:
Expand Down
92 changes: 92 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
###############
# Base Python #
###############
FROM python:3.8-slim-buster AS base-autoapi

# Virtualenv PATH
ENV PATH="/opt/venv/bin:$PATH"


######################
# Base testing image #
######################
FROM base-autoapi AS base-testing-autoapi

RUN apt update --quiet 3 > /dev/null 2>&1 && \
apt install --no-install-recommends --yes --quiet 3 gnupg curl > /dev/null 2>&1 && \
curl -fsSL https://www.mongodb.org/static/pgp/server-4.2.asc | apt-key add - > /dev/null 2>&1 && \
echo "deb http://repo.mongodb.org/apt/debian buster/mongodb-org/4.2 main" > /etc/apt/sources.list.d/mongodb-org-4.2.list && \
apt update --quiet 3 > /dev/null 2>&1 && \
apt install --no-install-recommends --yes --quiet 3 mongodb-org-server=4.2.6 > /dev/null 2>&1


#################
# Builder image #
#################
FROM base-autoapi AS builder-autoapi

WORKDIR /app

# Create Virtualenv
RUN python -m venv /opt/venv

# Upgrade python tools
COPY requirements-tools.txt ./
RUN pip install --quiet --upgrade --requirement requirements-tools.txt

# Install python dependencies
COPY requirements.txt ./
RUN pip install --quiet --requirement requirements.txt

# Install AutoApi
COPY auto_api ./auto_api
COPY LICENSE setup.py setup.cfg ./
RUN pip install --quiet --no-dependencies .


#################
# Testing image #
#################
FROM base-testing-autoapi AS testing-autoapi

WORKDIR /app

# Installed python modules
COPY --from=builder-autoapi /opt/venv /opt/venv

# Install python dev dependencies
COPY requirements-dev.txt ./
RUN pip install --quiet --requirement requirements-dev.txt

# Run tests
COPY tests ./tests
COPY run_tests.py ./
RUN python run_tests.py


####################
# Production image #
####################
FROM base-autoapi AS runtime-autoapi

# Installed python modules
COPY --from=builder-autoapi /opt/venv /opt/venv

# AutoApi user
ARG user=app
RUN useradd --create-home $user

# AutoApi port
ARG port=8686
ENV PORT=$port
EXPOSE $port

# AutoApi entrypoint
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh

# Setup service
USER $user
WORKDIR /home/$user
ENTRYPOINT ["/entrypoint.sh"]
CMD ["--bind :", "echo $PORT"]
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@

[![PyPI pyversions](https://img.shields.io/pypi/pyversions/auto_api.svg)](https://pypi.org/project/auto-api/)
[![MIT license](https://img.shields.io/badge/License-MIT-blue.svg)](https://lbesson.mit-license.org/)
[![PyPI](https://img.shields.io/pypi/v/auto-api)](https://pypi.org/project/auto-api/)

[![GitHub tag (latest SemVer)](https://img.shields.io/github/v/tag/fvalverd/AutoApi?sort=semver)](https://github.com/fvalverd/AutoApi/releases)
[![PyPI](https://img.shields.io/pypi/v/auto-api)](https://pypi.org/project/auto-api/)
[![Docker Image Version (latest semver)](https://img.shields.io/docker/v/felipevalverde/autoapi?label=docker&sort=semver)](https://hub.docker.com/repository/docker/felipevalverde/autoapi)

[![tests](https://github.com/fvalverd/AutoApi/workflows/tests/badge.svg?branch=master)](https://github.com/fvalverd/AutoApi/actions?query=workflow%3A%22tests%22)
[![Build Status](https://travis-ci.org/fvalverd/AutoApi.svg?branch=master)](https://travis-ci.org/fvalverd/AutoApi?branch=master)
[![Coverage Status](https://coveralls.io/repos/github/fvalverd/AutoApi/badge.svg?branch=master)](https://coveralls.io/github/fvalverd/AutoApi?branch=master)
Expand Down
37 changes: 16 additions & 21 deletions auto_api/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@
from .views import get, post, delete, put, patch


class AutoApi(object):
class AutoApi(Flask):

def __init__(self, auth=False, cors=True, port=None):
super(AutoApi, self).__init__(self.__class__.__name__)
self.auth = auth
self.cors = cors
self.app = Flask(self.__class__.__name__)
config_autoapi(self, cors=cors, force_port=port)

# AutoApi operation routes
Expand All @@ -30,22 +30,22 @@ def __init__(self, auth=False, cors=True, port=None):
self.load_api_rest()

def welcome(self):
return message(u"Welcome to AutoApi.")
return message('Welcome to AutoApi.')

def _name(self, view):
return '{prefix}.{name}'.format(prefix=self.prefix, name=view.__name__)

def add(
self, path, view, api=None, no_auth=False,
self, path, view, api=None, skip_auth=False,
method='POST', role=None, all_methods=False, no_api=False
):
"""" Bind path with view on AutoApi """

self.app.add_url_rule(
rule=path,
endpoint=u"{}.{}".format(self.prefix, view.__name__),
view_func=secure(
self.app, view, role=role, api=api,
auth=self.auth and not no_auth, no_api=no_api
),
methods=all_methods and list(http_method_funcs) or [method],
auth = self.auth and not skip_auth
params = dict(view=view, role=role, api=api, auth=auth, no_api=no_api)
self.add_url_rule(
path, endpoint=self._name(view), view_func=secure(self, **params),
methods=all_methods and list(http_method_funcs) or [method]
)

def route(self, path, **kwargs):
Expand All @@ -57,22 +57,17 @@ def wrapper(view):

def load_operations(self):
""" Bind operations related with Authentication & Authorization """
skip_all_params = dict(skip_auth=True, all_methods=True, no_api=True)

# AutoApi welcome message
self.add(
'/', lambda: self.welcome(), no_auth=True,
all_methods=True, no_api=True
)
self.add('/', lambda: self.welcome(), **skip_all_params)

# Invalid operation message
self.add(
'/<api>', invalid_operation, no_auth=True,
all_methods=True, no_api=True
)
self.add('/<api>', invalid_operation, **skip_all_params)

# AutoApi auth operations
if self.auth:
self.add('/login', login, no_auth=True)
self.add('/login', login, skip_auth=True)
self.add('/logout', logout)
self.add('/user', user, role='admin')
self.add('/password', password)
Expand Down
22 changes: 18 additions & 4 deletions auto_api/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,35 @@

import click
from auto_api import AutoApi
from auto_api.mongodb import update_roles, ADMIN_KEYS


@click.command()
@click.group()
def cli():
pass


@cli.command()
@click.option('--auth', '-a', help='AutoApi with authentication', is_flag=True)
@click.option('--debug', '-d', help='Flask debug mode', is_flag=True)
@click.option('--host', '-h', help='AutoApi host', default='0.0.0.0')
@click.option('--port', '-p', help='AutoApi port', default=8686, type=int)
@click.option('--reloader', '-r', help='Use Flask reloader', is_flag=True)
def main(auth, debug, host, port, reloader):
def run(auth, debug, host, port, reloader):
autoapi = AutoApi(auth=auth)
autoapi.app.run(
autoapi.run(
host=host, port=port, use_reloader=reloader, debug=debug, threaded=True
)


@cli.command()
@click.option('--port', '-p', help='MongoDB port', default=None, type=int)
def update_admin(port):
autoapi = AutoApi(auth=True, port=port)
name = autoapi.config[ADMIN_KEYS['name']]
update_roles(autoapi, api='admin', user=name, roles={'admin': True})


if __name__ == '__main__':
# pylint: disable=no-value-for-parameter
main()
cli()
4 changes: 2 additions & 2 deletions auto_api/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,8 @@ def wrapper(*args, **kwargs):
@contextmanager
def check(app, api, role, auth=True):
authenticated, authorized = not auth, not auth
if auth and 'X-Email' in request.headers and 'X-Token' in request.headers:
email, token = request.headers['X-Email'], request.headers['X-Token']
email, token = [request.headers.get(key) for key in ('X-Email', 'X-Token')]
if auth and email and token:
with admin(app) as client:
info, _ = get_custom_data(app, api, client, email)
if info is not None and info.get('tokens'):
Expand Down
13 changes: 7 additions & 6 deletions auto_api/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,31 +13,32 @@ def config_autoapi(
):
_config_logging(autoapi, level=logging_level)
if cors:
CORS(autoapi.app, resources={r'/*': {'origins': '*'}})
CORS(autoapi, resources={r'/*': {'origins': '*'}})
_read_config(autoapi, force_port=force_port)


def _config_logging(autoapi, level):
stream_handler = logging.StreamHandler()
stream_handler.setLevel(level)
autoapi.app.logger.addHandler(stream_handler)
autoapi.logger.addHandler(stream_handler)


def _read_config(autoapi, force_port=None):
if os.environ.get(MONGO_KEYS['host']):
autoapi.app.config[MONGO_KEYS['host']] = os.environ[MONGO_KEYS['host']]
autoapi.config[MONGO_KEYS['host']] = os.environ[MONGO_KEYS['host']]
else:
raise AutoApiMissingAdminConfig('Check your configuration !')
if force_port is not None:
autoapi.app.config[MONGO_KEYS['port']] = force_port
autoapi.config[MONGO_KEYS['port']] = force_port
elif os.environ.get(MONGO_KEYS['port']):
autoapi.app.config[MONGO_KEYS['port']] = os.environ[MONGO_KEYS['port']]
port = int(os.environ[MONGO_KEYS['port']])
autoapi.config[MONGO_KEYS['port']] = port
else:
raise AutoApiMissingAdminConfig('Check your configuration !')
if autoapi.auth:
# Read MongoDB admin credentials
for key in ADMIN_KEYS.values():
if os.environ.get(key):
autoapi.app.config[key] = os.environ[key]
autoapi.config[key] = os.environ[key]
else:
raise AutoApiMissingAdminConfig('Check your configuration !')

0 comments on commit 49b2ef0

Please sign in to comment.