treetrail-backend/src/treetrail/application.py
2024-10-23 16:19:51 +02:00

249 lines
6.6 KiB
Python
Executable file

#!/usr/bin/env python
import logging
import sys
from contextlib import asynccontextmanager
try:
import coloredlogs # type: ignore
except ImportError:
pass
else:
coloredlogs.install()
from fastapi import FastAPI, responses
from fastapi.staticfiles import StaticFiles
from treetrail.config import conf, get_cache_dir, create_dirs
from treetrail.plantekey import setup as setup_plantekey, pek_app
from treetrail.api_v1 import api_app
from treetrail.tiles import tiles_app, registry as tiles_registry
from treetrail.attachments import attachment_app
from treetrail.database import create_db
from treetrail.utils import mkdir
@asynccontextmanager
async def lifespan(app: FastAPI):
create_dirs()
setup_plantekey(app)
await create_db()
await tiles_registry.setup(app)
yield
await tiles_registry.shutdown(app)
app = FastAPI(
title=conf.app.title,
lifespan=lifespan,
version=conf.version,
default_response_class=responses.ORJSONResponse,
)
api_app.mount('/plantekey', pek_app)
app.mount(f'{conf.base_href}/v1', api_app)
app.mount(f'{conf.base_href}/tiles', tiles_app)
app.mount(f'{conf.base_href}/attachment', attachment_app)
app.mount(
f'{conf.base_href}/static/cache',
StaticFiles(directory=mkdir(get_cache_dir())),
name='static_generated'
)
def _main(argv=None):
from argparse import ArgumentParser
arg_parser = ArgumentParser(
description="fastapi Application server",
prog="fastapi"
)
arg_parser.add_argument(
'--path',
help='Path of socket file',
)
arg_parser.add_argument(
"-H", "--hostname",
help="TCP/IP hostname to serve on (default: %(default)r)",
default="localhost"
)
arg_parser.add_argument(
"-P", "--port",
help="TCP/IP port to serve on",
type=int,
)
arg_parser.add_argument(
"-c", "--create-db",
help="Create tables in database",
action="store_true"
)
arg_parser.add_argument(
"--username",
help="Create or update a user in database",
type=str,
)
arg_parser.add_argument(
"--add-role",
help="Add the role",
type=str,
)
arg_parser.add_argument(
"--add-user-role",
help="Add the role to the user",
type=str,
)
arg_parser.add_argument(
"--password",
help="Set the password for a user in database",
type=str,
)
arg_parser.add_argument(
"--full-name",
help="Set the full name for a user in database",
type=str,
)
arg_parser.add_argument(
"--email",
help="Set the email for a user in database",
type=str,
)
arg_parser.add_argument(
"--enable",
help="Enable user",
action="store_true"
)
arg_parser.add_argument(
"--disable",
help="Disable user",
action="store_true"
)
arg_parser.add_argument(
"--delete-user",
help="Delete user",
action="store_true"
)
arg_parser.add_argument(
"--import-trees",
help="Import trees (eg. gpkg file). Images can be imported.",
type=str,
)
arg_parser.add_argument(
"--layers",
help="Layers to import.",
nargs='*',
type=str,
)
arg_parser.add_argument(
"--import-zones",
help="Import zones (eg. gpkg file).",
type=str,
)
arg_parser.add_argument(
"--import-plantekey-trees-to-trail",
help="Import trees from plantekey web site. Provide the trail id.",
type=str,
)
arg_parser.add_argument(
"--import-plantekey-plants",
help="Import plants from plantekey web site",
action="store_true"
)
arg_parser.add_argument(
"--list-layers",
help="List layers in the geodata file",
type=str,
)
arg_parser.add_argument(
"-d", "--debug", '-d',
help="Set debug logging",
action="store_true"
)
args = arg_parser.parse_args()
if args.debug:
logging.root.setLevel(logging.DEBUG)
## For ipdb:
logging.getLogger('parso').setLevel(logging.WARNING)
if args.create_db:
from treetrail.database import create_db
import asyncio
asyncio.run(create_db())
sys.exit(0)
if args.enable:
from treetrail.security import enable_user
import asyncio
asyncio.run(enable_user(args.username))
sys.exit(0)
if args.disable:
from treetrail.security import enable_user
import asyncio
asyncio.run(enable_user(args.username, False))
sys.exit(0)
if args.add_role:
from treetrail.security import add_role
import asyncio
asyncio.run(add_role(args.add_role))
sys.exit(0)
if args.add_user_role:
from treetrail.security import add_user_role
import asyncio
if not args.username:
print('Please provide username')
sys.exit(1)
asyncio.run(add_user_role(args.username, args.add_user_role))
sys.exit(0)
if args.delete_user:
from treetrail.security import delete_user
import asyncio
asyncio.run(delete_user(args.username))
sys.exit(0)
if args.list_layers:
from treetrail.import_cli import list_layers
list_layers(args.list_layers)
sys.exit(0)
if args.import_trees:
from treetrail.import_cli import import_trees
import_trees(args)
sys.exit(0)
if args.import_zones:
from treetrail.import_cli import import_zones
import_zones(args)
sys.exit(0)
if args.import_plantekey_plants:
from treetrail.import_cli import import_plantekey_plants
import asyncio
asyncio.run(import_plantekey_plants(args))
sys.exit(0)
if args.import_plantekey_trees_to_trail:
from treetrail.import_cli import import_plantekey_trees
import_plantekey_trees(args)
sys.exit(0)
if args.username:
from treetrail.security import create_user
import asyncio
asyncio.run(create_user(**vars(args)))
sys.exit(0)
print(
'This application needs to be run with an asgi server like uvicorn.',
'For example:',
'uvicorn application:app',
'or:',
'uvicorn application:app --port 5002',
'or (for development):',
'uvicorn --reload application:app --uds /var/run/treetrail.socket',
'or (for production):',
'uvicorn --loop uvloop application:app --port 5002',
sep='\n'
)
if __name__ == '__main__':
_main()