This commit is contained in:
parent
ff978b5f73
commit
950c369455
@ -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:
|
||||||
|
@ -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
|
||||||
|
@ -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:
|
||||||
|
@ -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 "$@"
|
||||||
|
7
makefile
7
makefile
@ -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
|
||||||
|
@ -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")
|
||||||
|
@ -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")
|
||||||
|
@ -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")
|
||||||
|
20
members_lumbung_space/nextcloud.py
Normal file
20
members_lumbung_space/nextcloud.py
Normal 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")],
|
||||||
|
)
|
@ -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."""
|
||||||
|
|
||||||
|
@ -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
|
||||||
)
|
)
|
||||||
|
@ -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
22
poetry.lock
generated
@ -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"},
|
||||||
|
@ -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"
|
||||||
|
Loading…
Reference in New Issue
Block a user