{"id":14065333,"url":"https://github.com/elixir-cloud-aai/foca","last_synced_at":"2025-05-12T15:02:59.109Z","repository":{"id":39396408,"uuid":"238483669","full_name":"elixir-cloud-aai/foca","owner":"elixir-cloud-aai","description":"Opinionated Flask microservice archetype for quick OpenAPI-based microservice development","archived":false,"fork":false,"pushed_at":"2024-04-08T15:43:47.000Z","size":471,"stargazers_count":16,"open_issues_count":19,"forks_count":11,"subscribers_count":20,"default_branch":"dev","last_synced_at":"2024-04-13T09:04:08.124Z","etag":null,"topics":["api","flask","mongodb","openapi","openapi3","rest-api","swagger"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/elixir-cloud-aai.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2020-02-05T15:30:51.000Z","updated_at":"2024-04-25T06:37:55.829Z","dependencies_parsed_at":"2024-04-25T06:48:25.346Z","dependency_job_id":null,"html_url":"https://github.com/elixir-cloud-aai/foca","commit_stats":{"total_commits":79,"total_committers":12,"mean_commits":6.583333333333333,"dds":0.6075949367088608,"last_synced_commit":"d52e16218e953b34125afb4d541c0e3b47cd4336"},"previous_names":[],"tags_count":14,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/elixir-cloud-aai%2Ffoca","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/elixir-cloud-aai%2Ffoca/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/elixir-cloud-aai%2Ffoca/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/elixir-cloud-aai%2Ffoca/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/elixir-cloud-aai","download_url":"https://codeload.github.com/elixir-cloud-aai/foca/tar.gz/refs/heads/dev","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253761773,"owners_count":21960215,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api","flask","mongodb","openapi","openapi3","rest-api","swagger"],"created_at":"2024-08-13T07:04:26.158Z","updated_at":"2025-05-12T15:02:59.003Z","avatar_url":"https://github.com/elixir-cloud-aai.png","language":"Python","funding_links":[],"categories":["Python"],"sub_categories":[],"readme":"# ![FOCA_logo][foca-logo] \u0026ensp;_Develop Flask microservices quickly!_\n\n[![License][badge-license]][badge-url-license]\n[![Build_status][badge-build-status]][badge-url-build-status]\n[![Docs][badge-docs]][badge-url-docs]\n[![Coverage][badge-coverage]][badge-url-coverage]\n[![GitHub_tag][badge-github-tag]][badge-url-github-tag]\n[![PyPI_release][badge-pypi]][badge-url-pypi]\n\n**FOCA** (**F**lask-**O**penAPI-**C**onnexion-**A**rchetype) is an opinionated\narchetype that enables fast development of [OpenAPI][res-openapi]-based HTTP\nAPI microservices in [Flask][res-flask], leveraging the excellent\n[Connexion][res-connexion] framework.\n\nFOCA reduces the required boilerplate code to fire up your app to a bare\nminimum and allows you to _**focus on your application logic**_. It also avoids\nunnecessary code repetition and introduces cross-service consistency when\ndeveloping multiple applications. Simply write a configuration file, pass\nit to FOCA and you're good to go!\n\nCurrently supported features:\n\n* Manage app configuration\n* Handle exceptions\n* Register OpenAPI 2.x/3.x specifications\n* Protect endpoints via [JWT][res-jwt] validation\n* Register [MongoDB][res-mongo-db] collections\n* Run asynchronous tasks via [RabbitMQ][res-rabbitmq] \u0026 [Celery][res-celery]\n* [CORS][res-cors] support\n\nCheck the [API docs][badge-url-docs] for further details.\n\n## Table of Contents\n\n* [Usage](#usage)\n* [Configuration](#configuration)\n  * [Configuring OpenAPI specifications](#configuring-openapi-specifications)\n  * [Configuring MongoDB](#configuring-mongodb)\n  * [Configuring exceptions](#configuring-exceptions)\n  * [Configuring asynchronous tasks](#configuring-asynchronous-tasks)\n  * [Configuring logging](#configuring-logging)\n  * [Configuring security](#configuring-security)\n  * [Configuring the server](#configuring-the-server)\n  * [Custom configuration](#custom-configuration)\n  * [Accessing configuration parameters](#accessing-configuration-parameters)\n* [Utilities](#utilities)\n  * [Database utilities](#database-utilities)\n  * [Logging utitlies](#logging-utilities)\n  * [Miscellaneous utilities](#miscellaneous-utilities)\n  * [Access Control utilities](#access-control-utilities)\n* [Contributing](#contributing)\n* [Versioning](#versioning)\n* [License](#license)\n* [Contact](#contact)\n\n## Usage\n\n(1) Install the [FOCA package][badge-url-pypi] with `pip`:\n\n```bash\npip install foca\n```\n\n(2) Create a [configuration](#configuration) file.\n\n(3) Import the FOCA class and pass your config file:\n\n```python\nfrom foca import Foca\n\nfoca = Foca(config_file=\"path/to/my/app/config.yaml\")\napp = foca.create_app()  # returns a Connexion app instance\n```\n\n(4) Start your [Flask][res-flask] app as usual.\n\n![Hint][img-hint] _**Check out the [Petstore example application][example]\nshipped with this repository to see FOCA in action!**_\n\n## Configuration\n\n![Hint][img-hint] _**In order to get you started writing your own app\nconfiguration, you can copy the [**annotated template**][config-template]\nshipped with this repository and modify it.**_\n\nIn order to use FOCA functionalities, you must create a [YAML][res-yaml]\nconfiguration file that includes keyword sections reserved by FOCA. The\nfollowing top-level sections are interpreted by FOCA (exhaustive; links are\nprovided to the corresponding sections in this documentation, as well as to the\ncorresponding models in the [API docuementation][badge-url-docs]):\n\n* [`api`](#configuring-openapi-specifications) / [model][docs-models-api]\n* [`db`](#configuring-mongodb) / [model][docs-models-db]\n* [`exceptions`](#configuring-exceptions) / [model][docs-models-exceptions]\n* [`jobs`](#configuring-asynchronous-tasks) / [model][docs-models-jobs]\n* [`log`](#configuring-logging) / [model][docs-models-log]\n* [`security`](#configuring-security) / [model][docs-models-security]\n* [`server`](#configuring-the-server) / [model][docs-models-server]\n\n**_Any values passed to reserved keywords are automatically validated_**, and a\ncorresponding informative exception will be raised whenever a value does not\nadhere to the corresponding model as described in the [API\ndocumentation][docs-models]. If you do _not_ want to make use of a specific\nFOCA functionality, simply omit the corresponding section.\n\n### Configuring OpenAPI specifications\n\nThe `api` section is used to specify any [OpenAPI][res-openapi] specifications\nconsumed as part of your application. Essentially, FOCA adds a wrapper around\n[Connexion][res-connexion], which validates requests/responses and can serve\nthe specifications as well as a [Swagger][res-swagger]-based user interface to\nexplore the API. FOCA supports multiple specification files (versions\nSwagger/OpenAPI 2.x, OpenAPI 3.x and mixed) and multiple fragments thereof, and\nit adds additional features that allow easy modification of specifications on\nthe fly. In particular, links to routers and security definitions can be added\nto each specified endpoint.\n\n_Example:_\n\n```yaml\napi:\n  specs:\n    - path:\n        - path/to/openapi/specs.yaml\n        - path/to/openapi/additions.yaml\n      add_operation_fields:\n        x-openapi-router-controller: myapi.controllers\n      add_security_fields:\n        x-bearerInfoFunc: app.validate_token\n      disable_auth: False\n      connexion:\n        strict_validation: True\n        validate_responses: True\n        options:\n          swagger_ui: True\n          serve_spec: True\n    - path:\n        - path/to/openapi/other_specs.yaml\n```\n\n\u003e In this example, the configuration file lists two separate specifications.\n\u003e The first is a composite one that FOCA will compile from two files,\n\u003e `path/to/openapi/specs.yaml` and `path/to/openapi/additions.yaml`. It comes\n\u003e with a range of different explicitly specified parameters to further\n\u003e customize the specification itself (classes/functions implementing\n\u003e controllers and token validation are linked to each endpoint via\n\u003e `add_operation_fields`; `x-openapi-router-controller` and `x-bearerInfoFunc`\n\u003e can be used to link controller functions/classes and authorization validation\n\u003e functions to endpoints, respectively. Furthermore, a flag to disable the need\n\u003e for passing authorization tokens and several [Connexion][res-connexion]\n\u003e options are explicitly set for this specification. In contrast, only the path\n\u003e to a single file is specified for the second specification, implying default\n\u003e values for all other options.  \n\u003e  \n\u003e Further support for validating authorization can also be added to\n\u003e specifications via the `add_security_fields` parameter under `specs` (not\n\u003e shown here). Cf. the [API model][docs-models-api] for this and other options,\n\u003e as well as further details.\n\n### Configuring MongoDB\n\nFOCA can register one or more [MongoDB][res-mongo-db] databases and/or\ncollections for you. To use that functionality, simply include the top-level\n`db` keyword section in your configuration file and tune its behavior through\nthe available parameters.\n\n_Example:_\n\n```yaml\ndb:\n  host: mongodb\n  port: 27017\n  dbs:\n    myDb:\n      collections:\n        myCollection:\n          indexes:\n            - keys:\n                id: 1\n              options:\n                'unique': True\n        mySecondCollection:\n          indexes:\n            - keys:\n                other_id: 1\n    myOtherDb:\n      collections:\n        myThirdCollection:\n          indexes:\n            - keys:\n                third_id: 1\n```\n\n\u003e In this example, two databases (`myDb` and `myOtherDb`) are configured, the\n\u003e former with two and the latter with one collection (`myCollection`,\n\u003e `mySecondCollection` and `myThirdCollection`, respectively). FOCA will\n\u003e automatically register and initialize these databases and collections for you\n\u003e and add convenient clients to the app instance (accessible as children of\n\u003e `current_app.config.foca` in an [application\n\u003e context][res-flask-app-context]). The collections would be indexed by keys\n\u003e `id`, `other_id` and `third_id`, respectively. Out of these, only `id`\n\u003e will be required to be unique.  \n\u003e  \n\u003e Cf. the [API model][docs-models-db] for further options and details.\n\n### Configuring exceptions\n\nFOCA provides a convenient, configurable exception handler and a simple way\nof adding new exceptions to be used with that handler. To use it, specify a\ntop-level `exceptions` section in the app configuration file.\n\n_Example:_\n\n```yaml\nexceptions:\n  required_members: [['msg'], ['status']]\n  status_member: ['status']\n  exceptions: my_app.exceptions.exceptions\n  logging: one_line\n```\n\n\u003e This example configuration would attach the exceptions defined in the\n\u003e `my_app.exceptions.exceptions` dictionary to the exception handler. The\n\u003e exception handler ensures that every exception in that dictionary defines\n\u003e at least members `msg` and `status`. Out of these, `status` will be used\n\u003e to inform the status code for the error response. Exceptions processed via\n\u003e FOCA's exception handler will be automatically logged, if requested. In this\n\u003e case, the handler is configured to log all errors verbosely (including any\n\u003e traceback information, if applicable) on a single line (other rendering\n\u003e options are also supported).\n\u003e  \n\u003e You may further configure optional members, a list of `public members` (to be\n\u003e included in error responses) and `private members` (only visible in logs).\n\u003e Cf. the [API model][docs-models-exceptions] for further options and details.\n\n### Configuring asynchronous tasks\n\nFOCA offers limited support for running asynchronous tasks via the\n[RabbitMQ][res-rabbitmq] broker and [Celery][res-celery]. To make use of it,\ninclude the `jobs` top-level section in the app configuration file.\n\n_Example:_\n\n```yaml\njobs:\n  host: rabbitmq\n  port: 5672\n  backend: 'rpc://'\n  include:\n    - my_app.tasks.my_task_1\n    - my_app.tasks.my_task_2\n```\n\n\u003e This config attaches the `rabbitmq` broker host running on port `5672` to\n\u003e FOCA and registers the tasks found in modules `my_task_1` and `my_task_2`.  \n\u003e  \n\u003e Cf. the [API model][docs-models-jobs] for further details.  \n\nThe `foca.Foca` class provides a method `.create_celery_app()` that you can\nuse in your Celery worker entry point to crate a Celery app, like so:\n\n```py\nfrom foca import Foca\n\nfoca = Foca(config=\"my_app/config.yaml\")\nmy_celery_app = foca.create_celery_app()\n```\n\n### Configuring logging\n\nFOCA allows you to specify a YAML-based logging configuration to control your\napplication's logging behavior in an effort to provide a single configuration\nfile for every application. To use it, simply add a `log` top-level section in\nyour app configuration file.\n\n_Example:_\n\n```yaml\nlog:\n  version: 1\n  disable_existing_loggers: False\n  formatters:\n    standard:\n      class: logging.Formatter\n      style: \"{\"\n      format: \"[{asctime}: {levelname:\u003c8}] {message} [{name}]\"\n  handlers:\n    console:\n      class: logging.StreamHandler\n      level: 20\n      formatter: standard\n      stream: ext://sys.stderr\n  root:\n    level: 10\n    handlers: [console]\n```\n\n\u003e The logging configuration is simply passed on to Python's `logging' package,\n\u003e and so it has to conform with that [package's\n\u003e requirements][res-python-logging]. See [here][res-python-logging-how-to] for\n\u003e more info.\n\n### Configuring security\n\nFOCA offers some convenience functionalities for securing your app.\nSpecifically, it allows you to configure the validation of [JSON Web\nToken (JWT)][res-jwt]-based authorization, a [Casbin][res-casbin]-based access\ncontrol model, and the use of [cross-origin resource sharing (CORS)][res-cors].\nTo make use of them, include the `security` top-level section in your app\nconfiguration, as well as the desired sublevel section(s):\n\n```yaml\nsecurity:\n  auth:\n    algorithms:\n      - RS256\n    allow_expired: False\n    validation_methods:\n      - userinfo\n      - public_key\n    validation_checks: any\n  access_control:\n    api_specs: 'path/to/your/access/control/specs'\n    api_controllers: 'path/to/your/access/control/spec/controllers'\n    api_route: '/route/to/access_control_api'\n    db_name: access_control_db_name\n    collection_name: access_control_collection_name\n    model: access_control_model_definition\n  cors:\n    enabled: True\n```\n\n\u003e In this example, the validation of JWT Bearer tokens would make use of the\n\u003e `RS256` algorithm, would not allow expired tokens and would grant access to\n\u003e a protected endpoint if `any` of the two listed validation methods (via the\n\u003e identity provider's `/userinfo` endpoint or its JSON Web Key (JWK) public\n\u003e key. Furthermore, the application created with this config would provide\n\u003e an access control model `model`. Corresponding permissions could be accessed\n\u003e and altered by a user with admin permissions via the dedicated endpoints\n\u003e defined in the `api_specs`, operationalized by the controllers in\n\u003e `api_controllers` and hosted at `api_route`. Permissions will be stored in\n\u003e collection `collection_name` of a dedicated MongoDB database `db_name`.\n\u003e Finally, CORS would be enabled for this application.\n\u003e  \n\u003e Cf. the [API model][docs-models-security] for further options and details.\n\n**Note:** A detailed explaination of the access control implementation can be\nfound [here][docs-access-control].\n\n### Configuring the server\n\nFOCA allows you to pass certain basic configuration options to your Flask\napplication. To modify defaults, include the top-level `server` keyword section\nin your app configuration file:\n\n```yaml\nserver:\n  host: '0.0.0.0'\n  port: 8080\n  debug: True\n  environment: development\n  use_reloader: False\n```\n\n\u003e This config would create an application server hosting a Flask `development`\n\u003e environment at `0.0.0.0:8080`, Flask's debugger switched on, and its reloader\n\u003e off.\n\u003e  \n\u003e Cf. the [API model][docs-models-server] for further options and details.\n\n### Custom configuration\n\nIf you would like FOCA to validate your custom app configuration (e.g.,\nparameters required for individual controllers, you can provide a path, in\ndot notation, to a [`pydantic`][res-pydantic] `BaseModel`-derived model. FOCA\nthen tries to instantiate the model class with any custom parameters listed\nunder keyword section `custom`.\n\nSuppose you have a model like the following defined in module\n`my_app.custom_config`:\n\n```py\nfrom pydantic import BaseModel\n\n\nclass CustomConfig(BaseModel):\n    my_param: int = 5\n```\n\nAnd you have, in your app configuration file `my_app/config.yaml`, the\nfollowing section:\n\n```console\ncustom:\n  my_param: 10\n```\n\nYou can then have FOCA validate your custom configuration against the\n`CustomConfig` class by including it in the `Foca()` call like so:\n\n```py\nfrom foca import Foca\n\nfoca = Foca(\n  config=\"my_app/config.yaml\",\n  custom_config_model=\"my_app.custom_config.CustomConfig\",\n)\nmy_app = foca.create_app()\n```\n\nWe recommend that, when defining your `pydantic` model, that you supply\ndefault values wherever possible. In this way, the custom configuration\nparameters will always be available, even if not explicitly listed in the app\nconfiguration (like with the FOCA-specific parameters).\n\n\u003e Note that there is tooling available to automatically generate `pydantic`\n\u003e models from different file formats like JSON Schema etc. See here for the\n\u003e [datamodel-code-generator][res-datamodel-code-generator] project.\n\nApart from the reserved keyword sections listed above, you are free to include\nany other sections and parameters in your app configuration file. FOCA will\nsimply attach these to your application instance as described\n[above](#configuration) and shown [below](#accessing-configuration-parameters).\nNote, however, that any such parameters need to be _manually_ validated. The\nsame is true if you include a `custom` section but do _not_ provide a\nvalidation model class via the `custom_config_model` parameter when\ninstantiating `Foca`.\n\n_Example:_\n\n```yaml\nmy_custom_param: 'some_value'\n\nmy_custom_param_section:\n  another_custom_param: 3\n  my_custom_list_param:\n    - 1\n    - 2\n    - 3\n```\n\n### Accessing configuration parameters\n\nOnce the application is created using `foca()`, one can easily access any\nconfiguration parameters from within the [application\ncontext][res-flask-app-context] through `current_app.config.foca like so:\n\n```python\nfrom flask import current_app\n\napp_config = current_app.config.foca\n\ndb = app_config.db\napi = app_config.api\nserver = app_config.server\nexceptions = app_config.exceptions\nsecurity = app_config.security\njobs = app_config.jobs\nlog = app_config.log\napp_specific_param = current_app.config['app_specific_param']\n```\n\n_Outside of the application context_, configuration parameters are available\nvia `app.config.foca` in a similar way.\n\n### More examples\n\nApart from the [annotated template][config-template], you can also check\nout the [configuration file][config-petstore] of the [Petstore app][example]\nfor another example.\n\n![Hint][img-hint] _**Or why not explore [apps that already use\nFOCA][res-using-foca]?**_\n\n## Utilities\n\nFOCA provides some functions that may be useful for several applications.\nSimply import them if you want to use them.\n\n### Database utilities\n\nFOCA provides the following general-purpose MongoDB controllers:\n\n* Fetch latest object given the db `collection`:\n\n```python\nfrom foca.utils.db import find_one_latest\n\nlatest_object = find_one_latest(\"your_db_collection_instance\")\n```\n\n* Fetch latest object identifier (`id`) given the db `collection`:\n\n```python\nfrom foca.utils.db import find_id_latest\n\nlatest_object_id = find_id_latest(\"your_db_collection_instance\")\n```\n\n### Logging utilities\n\nFOCA provides a decorator that can be used on any route to automatically log\nany requests and/or responses passing through that route:\n\n```python\nfrom foca.utils.logging import log_traffic\n\n@log_traffic(log_request=True, log_response=True, log_level=20)\ndef your_controller():\n    pass\n```\n\n\u003e The above decorater will log both requests and responses with the specified\n\u003e logging level (`20`, or `INFO`).\n\n### Miscellaneous utilities\n\n* Generate a random object from a given character set:\n\n```python\nimport string\n\nfrom foca.utils.misc import generate_id\n\nobj_id = generate_id(charset=string.digits, length=6)\n```\n\n\u003e The above function processes and returns a random `obj_id` of length `6`\n\u003e consisting of only digits (`string.digits`).\n\n### Access Control utilities\n\nFOCA provides a decorator that can be used on any route to automatically\nvalidate request on the basis of permission rules.\n\n```python\nfrom foca.security.access_control.register_access_control import (\n    check_permissions\n)\n\n@check_permissions\ndef your_controller():\n    pass\n```\n\n## Contributing\n\nThis project is a community effort and lives off your contributions, be it in\nthe form of bug reports, feature requests, discussions, or fixes and other code\nchanges. Please refer to our organization's [contributing\nguidelines][res-elixir-cloud-contributing] if you are interested to contribute.\nPlease mind the [code of conduct][res-elixir-cloud-coc] for all interactions\nwith the community.\n\n## Versioning\n\nThe project adopts [semantic versioning][res-semver]. Currently the service\nis in beta stage, so the API may change without further notice.\n\n## License\n\nThis project is covered by the [Apache License 2.0][license-apache] also\n[shipped with this repository][license].\n\n## Contact\n\nThe project is a collaborative effort under the umbrella of [ELIXIR Cloud \u0026\nAAI][org-elixir-cloud]. Follow the link to get in touch with us via chat or\nemail. Please mention the name of this service for any inquiry, proposal,\nquestion etc.\n\n![Logo_banner][img-logo-banner]\n\n[badge-build-status]: \u003chttps://github.com/elixir-cloud-aai/foca/actions/workflows/checks.yml/badge.svg\u003e\n[badge-coverage]: \u003chttps://codecov.io/gh/elixir-cloud-aai/foca/branch/dev/graph/badge.svg?branch=dev\u003e\n[badge-docs]: \u003chttps://readthedocs.org/projects/foca/badge/\u003e\n[badge-github-tag]: \u003chttps://img.shields.io/github/v/tag/elixir-cloud-aai/foca?color=C39BD3\u003e\n[badge-license]: \u003chttps://img.shields.io/badge/license-Apache%202.0-blue.svg\u003e\n[badge-pypi]: \u003chttps://img.shields.io/pypi/v/foca.svg?style=flat\u0026color=C39BD3\u003e\n[badge-url-build-status]: \u003chttps://github.com/elixir-cloud-aai/foca/actions/workflows/checks.yml\u003e\n[badge-url-coverage]: \u003chttps://codecov.io/gh/elixir-cloud-aai/foca?branch=dev\u003e\n[badge-url-docs]: \u003chttps://foca.readthedocs.io/en/latest/\u003e\n[badge-url-github-tag]: \u003chttps://github.com/elixir-cloud-aai/foca/releases\u003e\n[badge-url-license]: \u003chttp://www.apache.org/licenses/LICENSE-2.0\u003e\n[badge-url-pypi]: \u003chttps://pypi.python.org/pypi/foca\u003e\n[config-template]: templates/config.yaml\n[config-petstore]: examples/petstore/config.yaml\n[docs-access-control]: docs/access_control/README.md\n[docs-models]: \u003chttps://foca.readthedocs.io/en/latest/modules/foca.models.html\u003e\n[docs-models-api]: \u003chttps://foca.readthedocs.io/en/latest/modules/foca.models.html#foca.models.config.APIConfig\u003e\n[docs-models-db]: \u003chttps://foca.readthedocs.io/en/latest/modules/foca.models.html#foca.models.config.DBConfig\u003e\n[docs-models-exceptions]: \u003chttps://foca.readthedocs.io/en/latest/modules/foca.models.html#foca.models.config.ExceptionConfig\u003e\n[docs-models-jobs]: \u003chttps://foca.readthedocs.io/en/latest/modules/foca.models.html#foca.models.config.JobsConfig\u003e\n[docs-models-log]: \u003chttps://foca.readthedocs.io/en/latest/modules/foca.models.html#foca.models.config.LogConfig\u003e\n[docs-models-security]: \u003chttps://foca.readthedocs.io/en/latest/modules/foca.models.html#foca.models.config.SecurityConfig\u003e\n[docs-models-server]: \u003chttps://foca.readthedocs.io/en/latest/modules/foca.models.html#foca.models.config.ServerConfig\u003e\n[example]: examples/petstore/README.md\n[foca-logo]: images/foca_logo_192px.png\n[img-hint]: images/hint.svg\n[img-logo-banner]: images/logo-banner.svg\n[license]: LICENSE\n[license-apache]: \u003chttps://www.apache.org/licenses/LICENSE-2.0\u003e\n[org-elixir-cloud]: \u003chttps://github.com/elixir-cloud-aai/elixir-cloud-aai\u003e\n[res-casbin]: \u003chttps://casbin.org/\u003e\n[res-celery]: \u003chttp://docs.celeryproject.org/\u003e\n[res-connexion]: \u003chttps://github.com/zalando/connexion\u003e\n[res-cors]: \u003chttps://flask-cors.readthedocs.io/en/latest/\u003e\n[res-elixir-cloud-coc]: \u003chttps://github.com/elixir-cloud-aai/elixir-cloud-aai/blob/dev/CODE_OF_CONDUCT.md\u003e\n[res-elixir-cloud-contributing]: \u003chttps://github.com/elixir-cloud-aai/elixir-cloud-aai/blob/dev/CONTRIBUTING.md\u003e\n[res-flask]: \u003chttp://flask.pocoo.org/\u003e\n[res-flask-app-context]: \u003chttps://flask.palletsprojects.com/en/1.1.x/appcontext/\u003e\n[res-jwt]: \u003chttps://jwt.io\u003e\n[res-mongo-db]: \u003chttps://www.mongodb.com/\u003e\n[res-openapi]: \u003chttps://www.openapis.org/\u003e\n[res-pydantic]: \u003chttps://pydantic-docs.helpmanual.io/\u003e\n[res-rabbitmq]: \u003chttps://www.rabbitmq.com/\u003e\n[res-semver]: \u003chttps://semver.org/\u003e\n[res-swagger]: \u003chttps://swagger.io/tools/swagger-ui/\u003e\n[res-using-foca]: \u003chttps://github.com/elixir-cloud-aai/foca/network/dependents\u003e\n[res-yaml]: \u003chttps://yaml.org/\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Felixir-cloud-aai%2Ffoca","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Felixir-cloud-aai%2Ffoca","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Felixir-cloud-aai%2Ffoca/lists"}