feat: resource map
continuous-integration/drone/push Build is failing Details

This commit is contained in:
cellarspoon 2022-01-10 16:20:47 +01:00
parent ff978b5f73
commit 950c369455
No known key found for this signature in database
GPG Key ID: 03789458B3D0C410
14 changed files with 105 additions and 28 deletions

View File

@ -32,6 +32,7 @@ steps:
LETS_ENCRYPT_ENV: production LETS_ENCRYPT_ENV: production
SECRET_APP_SECRET_KEY_VERSION: v1 SECRET_APP_SECRET_KEY_VERSION: v1
SECRET_KEYCLOAK_CLIENT_SECRET_VERSION: v1 SECRET_KEYCLOAK_CLIENT_SECRET_VERSION: v1
SECRET_NEXTCLOUD_APP_SECRET_VERSION: v1
STACK_NAME: members_lumbung_space STACK_NAME: members_lumbung_space
trigger: trigger:
branch: branch:

View File

@ -9,9 +9,13 @@ KEYCLOAK_CLIENT_SECRET=barfoo
KEYCLOAK_DOMAIN=login.lumbung.space KEYCLOAK_DOMAIN=login.lumbung.space
KEYCLOAK_REALM=lumbung-space KEYCLOAK_REALM=lumbung-space
LETS_ENCRYPT_ENV=production LETS_ENCRYPT_ENV=production
NEXTCLOUD_API_BASE_URL=cloud.lumbung.space
NEXTCLOUD_APP_PASSWORD=fizzbang
NEXTCLOUD_USER=decentral1se
REDIS_DB=0 REDIS_DB=0
REDIS_HOST=localhost REDIS_HOST=localhost
REDIS_PORT=6379 REDIS_PORT=6379
SECRET_APP_SECRET_KEY_VERSION=v1 SECRET_APP_SECRET_KEY_VERSION=v1
SECRET_KEYCLOAK_CLIENT_SECRET_VERSION=v1 SECRET_KEYCLOAK_CLIENT_SECRET_VERSION=v1
SECRET_NEXTCLOUD_APP_SECRET_VERSION=v1
STACK_NAME=foo_example_com STACK_NAME=foo_example_com

View File

@ -13,12 +13,14 @@ services:
- KEYCLOAK_CLIENT_SECRET_FILE=/run/secrets/keycloak_client_secret - KEYCLOAK_CLIENT_SECRET_FILE=/run/secrets/keycloak_client_secret
- KEYCLOAK_DOMAIN - KEYCLOAK_DOMAIN
- KEYCLOAK_REALM - KEYCLOAK_REALM
- NEXTCLOUD_APP_SECRET_FILE=/run/secrets/nextcloud_app_secret
- REDIS_DB=0 - REDIS_DB=0
- REDIS_HOST=cache - REDIS_HOST=cache
- REDIS_PORT=6379 - REDIS_PORT=6379
secrets: secrets:
- app_secret_key - app_secret_key
- keycloak_client_secret - keycloak_client_secret
- nextcloud_app_secret
networks: networks:
- proxy - proxy
- internal - internal
@ -72,6 +74,9 @@ secrets:
keycloak_client_secret: keycloak_client_secret:
external: true external: true
name: ${STACK_NAME}_keycloak_client_secret_${SECRET_KEYCLOAK_CLIENT_SECRET_VERSION} name: ${STACK_NAME}_keycloak_client_secret_${SECRET_KEYCLOAK_CLIENT_SECRET_VERSION}
nextcloud_app_secret:
external: true
name: ${STACK_NAME}_nextcloud_app_secret_${SECRET_NEXTCLOUD_APP_SECRET_VERSION}
volumes: volumes:
redis: redis:

View File

@ -23,8 +23,8 @@ file_env() {
unset "$fileVar" unset "$fileVar"
} }
file_env "KEYCLOAK_CLIENT_SECRET" file_end "NEXTCLOUD_APP_SECRET"
file_env "APP_SECRET_KEY" file_env "APP_SECRET_KEY"
file_env "KEYCLOAK_CLIENT_SECRET"
echo "Passing it back to the upstream ENTRYPOINT/CMD..."
exec "$@" exec "$@"

View File

@ -3,12 +3,7 @@
.PHONY: run redis deploy .PHONY: run redis deploy
run: run:
@if [ ! -d ".venv" ]; then \ poetry run uvicorn members_lumbung_space.main:app --reload
python3 -m venv .venv && \
.venv/bin/pip install -U pip setuptools wheel poetry && \
.venv/bin/poetry install; \
fi
.venv/bin/poetry run uvicorn members_lumbung_space.main:app --reload
redis: redis:
@docker run -p 6379:6379 --name redis -d redis:6-alpine @docker run -p 6379:6379 --name redis -d redis:6-alpine

View File

@ -41,3 +41,8 @@ else:
# Automatically log folks in or show the default log in page? # Automatically log folks in or show the default log in page?
AUTOMATICALLY_LOG_IN = environ.get("AUTOMATICALLY_LOG_IN", False) AUTOMATICALLY_LOG_IN = environ.get("AUTOMATICALLY_LOG_IN", False)
# Nextcloud integration
NEXTCLOUD_API_BASE_URL = environ.get("NEXTCLOUD_API_BASE_URL")
NEXTCLOUD_APP_PASSWORD = environ.get("NEXTCLOUD_APP_PASSWORD")
NEXTCLOUD_USER = environ.get("NEXTCLOUD_USER")

View File

@ -3,6 +3,7 @@
from datetime import datetime as dt from datetime import datetime as dt
from datetime import timedelta from datetime import timedelta
import owncloud
from fastapi import Depends, Request from fastapi import Depends, Request
from humanize import naturaldelta from humanize import naturaldelta
@ -38,6 +39,9 @@ async def get_invites(request: Request, user=Depends(get_user)):
all_invites = {} all_invites = {}
for username in await request.app.state.redis.keys("*"): for username in await request.app.state.redis.keys("*"):
if username == "resource_map":
continue
invites = await request.app.state.redis.get(username) invites = await request.app.state.redis.get(username)
for invite in invites: for invite in invites:
@ -49,3 +53,8 @@ async def get_invites(request: Request, user=Depends(get_user)):
all_invites[username] = invites all_invites[username] = invites
return all_invites return all_invites
async def get_resource_map(request: Request):
"""Retrieve the resource map listing."""
return await request.app.state.redis.get("resource_map")

View File

@ -13,23 +13,15 @@ from members_lumbung_space.config import (
APP_LOG_LEVEL, APP_LOG_LEVEL,
APP_SECRET_KEY, APP_SECRET_KEY,
APP_THEME, APP_THEME,
REDIS_DB,
REDIS_HOST,
REDIS_PORT,
STATIC_DIR, STATIC_DIR,
TEMPLATE_DIR, TEMPLATE_DIR,
) )
from members_lumbung_space.exceptions import RequiresLoginException from members_lumbung_space.exceptions import RequiresLoginException
from members_lumbung_space.keycloak import init_keycloak from members_lumbung_space.keycloak import init_keycloak
from members_lumbung_space.nextcloud import init_resource_map
from members_lumbung_space.oidc import init_oidc from members_lumbung_space.oidc import init_oidc
from members_lumbung_space.redis import Redis from members_lumbung_space.redis import Redis, init_redis
from members_lumbung_space.routes import ( from members_lumbung_space.routes import health, invite, oidc, register, root
health,
invite,
oidc,
register,
root,
)
log = logging.getLogger("uvicorn") log = logging.getLogger("uvicorn")
log.setLevel(APP_LOG_LEVEL) log.setLevel(APP_LOG_LEVEL)
@ -50,10 +42,11 @@ async def http_exception_handler(request, exc):
@app.on_event("startup") @app.on_event("startup")
async def startup_event(): async def startup_event():
redis = Redis() await init_redis(app)
app.state.redis = await redis.create_pool( log.info("Initialised redis connection")
f"redis://{REDIS_HOST}:{REDIS_PORT}/{REDIS_DB}?encoding=utf-8"
) await init_resource_map(app)
log.info("Initialised the resource map")
@app.on_event("shutdown") @app.on_event("shutdown")

View File

@ -0,0 +1,20 @@
"""Nextcloud logic."""
import owncloud
async def init_resource_map(app):
"""Initialise resource map listing."""
from members_lumbung_space.config import (
NEXTCLOUD_API_BASE_URL,
NEXTCLOUD_APP_PASSWORD,
NEXTCLOUD_USER,
)
nextcloud = owncloud.Client(f"https://{NEXTCLOUD_API_BASE_URL}")
nextcloud.login(NEXTCLOUD_USER, NEXTCLOUD_APP_PASSWORD)
await app.state.redis.set(
"resource_map",
[f.get_name() for f in nextcloud.list("/", depth="infinity")],
)

View File

@ -5,6 +5,15 @@ import json
from aioredis import create_redis_pool from aioredis import create_redis_pool
async def init_redis(app):
from members_lumbung_space.config import REDIS_DB, REDIS_HOST, REDIS_PORT
redis = Redis()
app.state.redis = await redis.create_pool(
f"redis://{REDIS_HOST}:{REDIS_PORT}/{REDIS_DB}?encoding=utf-8"
)
class Redis: class Redis:
"""Redis cache.""" """Redis cache."""

View File

@ -4,6 +4,7 @@ from fastapi import APIRouter, Depends, Request
from members_lumbung_space.dependencies import ( from members_lumbung_space.dependencies import (
get_invites, get_invites,
get_resource_map,
get_user, get_user,
logged_in, logged_in,
) )
@ -13,9 +14,18 @@ router = APIRouter()
@router.get("/", dependencies=[Depends(logged_in)]) @router.get("/", dependencies=[Depends(logged_in)])
async def home( async def home(
request: Request, user=Depends(get_user), invites=Depends(get_invites) request: Request,
user=Depends(get_user),
invites=Depends(get_invites),
resource_map=Depends(get_resource_map),
): ):
context = {"request": request, "user": user, "invites": invites} context = {
"request": request,
"user": user,
"invites": invites,
"resource_map": resource_map,
}
return request.app.state.templates.TemplateResponse( return request.app.state.templates.TemplateResponse(
"admin.html", context=context "admin.html", context=context
) )

View File

@ -2,7 +2,6 @@
{% block content %} {% block content %}
<p> <p>
Hello, {{ user.preferred_username }} 👋 Hello, {{ user.preferred_username }} 👋
<small>(<a href="{{ url_for('logout') }}">logout</a>)</small>
</p> </p>
<div> <div>
@ -43,8 +42,14 @@
{% endif %} {% endif %}
<p> <p>
<a href="{{ url_for('invite_keycloak_create') }}">Generate an invite link</a> <a href="{{ url_for('invite_keycloak_create') }}">Generate</a>
</p> </p>
</div> </div>
<div>
<h2>Resource map</h2>
<p>(i have no idea how to render this)<p>
<div>{{ resource_map }}</div>
</div>
{% endblock %} {% endblock %}

22
poetry.lock generated
View File

@ -459,6 +459,25 @@ category = "dev"
optional = false optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
[[package]]
name = "pyocclient"
version = "0.4"
description = ""
category = "main"
optional = false
python-versions = "*"
develop = false
[package.dependencies]
requests = ">=2.0.1"
six = "*"
[package.source]
type = "git"
url = "https://github.com/decentral1se/pyocclient.git"
reference = "patched-madcap-branch"
resolved_reference = "be63a32f520b887948f20ae57ca887d85555f720"
[[package]] [[package]]
name = "python-dotenv" name = "python-dotenv"
version = "0.19.2" version = "0.19.2"
@ -681,7 +700,7 @@ python-versions = ">=3.7"
[metadata] [metadata]
lock-version = "1.1" lock-version = "1.1"
python-versions = "^3.9" python-versions = "^3.9"
content-hash = "ecf2a823da9679d30575e15c6fcb2eac6f1d9c323870831ba8c2f1fdc47e4fd1" content-hash = "0dc5935d876e202c05146d69858efaaf722d4a4ab91199b0634e40ef6cb209f3"
[metadata.files] [metadata.files]
aiofiles = [ aiofiles = [
@ -1055,6 +1074,7 @@ pyflakes = [
{file = "pyflakes-2.3.1-py2.py3-none-any.whl", hash = "sha256:7893783d01b8a89811dd72d7dfd4d84ff098e5eed95cfa8905b22bbffe52efc3"}, {file = "pyflakes-2.3.1-py2.py3-none-any.whl", hash = "sha256:7893783d01b8a89811dd72d7dfd4d84ff098e5eed95cfa8905b22bbffe52efc3"},
{file = "pyflakes-2.3.1.tar.gz", hash = "sha256:f5bc8ecabc05bb9d291eb5203d6810b49040f6ff446a756326104746cc00c1db"}, {file = "pyflakes-2.3.1.tar.gz", hash = "sha256:f5bc8ecabc05bb9d291eb5203d6810b49040f6ff446a756326104746cc00c1db"},
] ]
pyocclient = []
python-dotenv = [ python-dotenv = [
{file = "python-dotenv-0.19.2.tar.gz", hash = "sha256:a5de49a31e953b45ff2d2fd434bbc2670e8db5273606c1e737cc6b93eff3655f"}, {file = "python-dotenv-0.19.2.tar.gz", hash = "sha256:a5de49a31e953b45ff2d2fd434bbc2670e8db5273606c1e737cc6b93eff3655f"},
{file = "python_dotenv-0.19.2-py2.py3-none-any.whl", hash = "sha256:32b2bdc1873fd3a3c346da1c6db83d0053c3c62f28f1f38516070c4c8971b1d3"}, {file = "python_dotenv-0.19.2-py2.py3-none-any.whl", hash = "sha256:32b2bdc1873fd3a3c346da1c6db83d0053c3c62f28f1f38516070c4c8971b1d3"},

View File

@ -19,6 +19,7 @@ python-multipart = "^0.0.5"
python-keycloak = "^0.25.0" python-keycloak = "^0.25.0"
aiofiles = "^0.7.0" aiofiles = "^0.7.0"
email-validator = "^1.1.3" email-validator = "^1.1.3"
pyocclient = { git = "https://github.com/decentral1se/pyocclient.git", branch = "patched-madcap-branch" }
[tool.poetry.dev-dependencies] [tool.poetry.dev-dependencies]
black = "^21.6b0" black = "^21.6b0"