Further into invite link display
This commit is contained in:
parent
96e718db3a
commit
c5c856e6e9
@ -1,6 +1,8 @@
|
|||||||
"""Community Keycloak SSO user management."""
|
"""Community Keycloak SSO user management."""
|
||||||
|
|
||||||
import json
|
import json
|
||||||
|
from datetime import datetime as dt
|
||||||
|
from datetime import timedelta
|
||||||
from os import environ
|
from os import environ
|
||||||
from uuid import uuid4
|
from uuid import uuid4
|
||||||
|
|
||||||
@ -10,6 +12,7 @@ from authlib.integrations.starlette_client import OAuth, OAuthError
|
|||||||
from fastapi import Depends, FastAPI, HTTPException, Request
|
from fastapi import Depends, FastAPI, HTTPException, Request
|
||||||
from fastapi.responses import HTMLResponse, RedirectResponse
|
from fastapi.responses import HTMLResponse, RedirectResponse
|
||||||
from fastapi.templating import Jinja2Templates
|
from fastapi.templating import Jinja2Templates
|
||||||
|
from humanize import naturaldelta
|
||||||
from starlette.exceptions import HTTPException
|
from starlette.exceptions import HTTPException
|
||||||
from starlette.middleware.sessions import SessionMiddleware
|
from starlette.middleware.sessions import SessionMiddleware
|
||||||
|
|
||||||
@ -26,6 +29,8 @@ REDIS_DB = environ.get("REDIS_DB")
|
|||||||
REDIS_HOST = environ.get("REDIS_HOST")
|
REDIS_HOST = environ.get("REDIS_HOST")
|
||||||
REDIS_PORT = environ.get("REDIS_PORT")
|
REDIS_PORT = environ.get("REDIS_PORT")
|
||||||
|
|
||||||
|
INVITE_TIME_LIMIT = environ.get("INVITE_TIME_LIMIT")
|
||||||
|
|
||||||
app = FastAPI(docs_url=None, redoc_url=None)
|
app = FastAPI(docs_url=None, redoc_url=None)
|
||||||
app.add_middleware(SessionMiddleware, secret_key=APP_SECRET_KEY)
|
app.add_middleware(SessionMiddleware, secret_key=APP_SECRET_KEY)
|
||||||
templates = Jinja2Templates(directory="templates")
|
templates = Jinja2Templates(directory="templates")
|
||||||
@ -68,9 +73,24 @@ async def get_user(request: Request):
|
|||||||
return request.session.get("user")
|
return request.session.get("user")
|
||||||
|
|
||||||
|
|
||||||
|
async def get_invites(request: Request, user=Depends(get_user)):
|
||||||
|
username = user["preferred_username"]
|
||||||
|
invites = await app.state.redis.get(username)
|
||||||
|
if invites:
|
||||||
|
humanised = []
|
||||||
|
for invite in json.loads(invites):
|
||||||
|
invite["human_time"] = naturaldelta(
|
||||||
|
dt.fromisoformat(invite["time"])
|
||||||
|
+ timedelta(days=int(INVITE_TIME_LIMIT))
|
||||||
|
)
|
||||||
|
humanised.append(invite)
|
||||||
|
return humanised
|
||||||
|
return []
|
||||||
|
|
||||||
|
|
||||||
@app.on_event("startup")
|
@app.on_event("startup")
|
||||||
async def starup_event():
|
async def starup_event():
|
||||||
app.state.redis = create_redis_pool(
|
app.state.redis = await create_redis_pool(
|
||||||
f"redis://{REDIS_HOST}:{REDIS_PORT}/{REDIS_DB}?encoding=utf-8"
|
f"redis://{REDIS_HOST}:{REDIS_PORT}/{REDIS_DB}?encoding=utf-8"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -82,8 +102,10 @@ async def shutdown_event():
|
|||||||
|
|
||||||
|
|
||||||
@app.get("/", dependencies=[Depends(logged_in)])
|
@app.get("/", dependencies=[Depends(logged_in)])
|
||||||
async def home(request: Request, user=Depends(get_user)):
|
async def home(
|
||||||
context = {"request": request, "user": user}
|
request: Request, user=Depends(get_user), invites=Depends(get_invites)
|
||||||
|
):
|
||||||
|
context = {"request": request, "user": user, "invites": invites}
|
||||||
return templates.TemplateResponse("admin.html", context=context)
|
return templates.TemplateResponse("admin.html", context=context)
|
||||||
|
|
||||||
|
|
||||||
@ -125,6 +147,18 @@ async def logout(request: Request):
|
|||||||
return RedirectResponse(request.url_for("login"))
|
return RedirectResponse(request.url_for("login"))
|
||||||
|
|
||||||
|
|
||||||
@app.get("/invite/keycloak", dependencies=[Depends(logged_in)])
|
@app.get("/invite/keycloak/create", dependencies=[Depends(logged_in)])
|
||||||
async def invite_keycloak(request: Request):
|
async def invite_keycloak_create(
|
||||||
pass
|
request: Request, user=Depends(get_user), invites=Depends(get_invites)
|
||||||
|
):
|
||||||
|
invites.append({"link": str(uuid4()), "time": str(dt.now())})
|
||||||
|
app.state.redis.set(user["preferred_username"], json.dumps(invites))
|
||||||
|
return RedirectResponse(request.url_for("home"))
|
||||||
|
|
||||||
|
|
||||||
|
@app.get("/invite/keycloak/delete", dependencies=[Depends(logged_in)])
|
||||||
|
async def invite_keycloak_delete(
|
||||||
|
request: Request, user=Depends(get_user), invites=Depends(get_invites)
|
||||||
|
):
|
||||||
|
invite =request.query_params.get("invite")
|
||||||
|
# TODO
|
||||||
|
17
poetry.lock
generated
17
poetry.lock
generated
@ -239,6 +239,17 @@ sniffio = "*"
|
|||||||
brotli = ["brotlicffi (>=1.0.0,<2.0.0)"]
|
brotli = ["brotlicffi (>=1.0.0,<2.0.0)"]
|
||||||
http2 = ["h2 (>=3.0.0,<4.0.0)"]
|
http2 = ["h2 (>=3.0.0,<4.0.0)"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "humanize"
|
||||||
|
version = "3.7.1"
|
||||||
|
description = "Python humanize utilities"
|
||||||
|
category = "main"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.6"
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
tests = ["freezegun", "pytest", "pytest-cov"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "idna"
|
name = "idna"
|
||||||
version = "3.2"
|
version = "3.2"
|
||||||
@ -501,7 +512,7 @@ python-versions = ">=3.6.1"
|
|||||||
[metadata]
|
[metadata]
|
||||||
lock-version = "1.1"
|
lock-version = "1.1"
|
||||||
python-versions = "^3.9"
|
python-versions = "^3.9"
|
||||||
content-hash = "3b87d7d886ec83f9a136e2535f8e9b2802f1c680464022c2938abce0033e55bd"
|
content-hash = "0ba44935dd5a68706610677a7e54fa3ebcd6f5a68edd05a1e1ecb8dbd9ca5947"
|
||||||
|
|
||||||
[metadata.files]
|
[metadata.files]
|
||||||
aioredis = [
|
aioredis = [
|
||||||
@ -689,6 +700,10 @@ httpx = [
|
|||||||
{file = "httpx-0.18.1-py3-none-any.whl", hash = "sha256:ad2e3db847be736edc4b272c4d5788790a7e5789ef132fc6b5fef8aeb9e9f6e0"},
|
{file = "httpx-0.18.1-py3-none-any.whl", hash = "sha256:ad2e3db847be736edc4b272c4d5788790a7e5789ef132fc6b5fef8aeb9e9f6e0"},
|
||||||
{file = "httpx-0.18.1.tar.gz", hash = "sha256:0a2651dd2b9d7662c70d12ada5c290abcf57373b9633515fe4baa9f62566086f"},
|
{file = "httpx-0.18.1.tar.gz", hash = "sha256:0a2651dd2b9d7662c70d12ada5c290abcf57373b9633515fe4baa9f62566086f"},
|
||||||
]
|
]
|
||||||
|
humanize = [
|
||||||
|
{file = "humanize-3.7.1-py3-none-any.whl", hash = "sha256:a0dca9eb010dd1fab61819acaea54be344a4c22c77261f72ac4dbee183dd9a59"},
|
||||||
|
{file = "humanize-3.7.1.tar.gz", hash = "sha256:b8e7878f3063174b212bb82b9e5bee3b24bc47931e44df0bd34bcb1d8e0acf2f"},
|
||||||
|
]
|
||||||
idna = [
|
idna = [
|
||||||
{file = "idna-3.2-py3-none-any.whl", hash = "sha256:14475042e284991034cb48e06f6851428fb14c4dc953acd9be9a5e95c7b6dd7a"},
|
{file = "idna-3.2-py3-none-any.whl", hash = "sha256:14475042e284991034cb48e06f6851428fb14c4dc953acd9be9a5e95c7b6dd7a"},
|
||||||
{file = "idna-3.2.tar.gz", hash = "sha256:467fbad99067910785144ce333826c71fb0e63a425657295239737f7ecd125f3"},
|
{file = "idna-3.2.tar.gz", hash = "sha256:467fbad99067910785144ce333826c71fb0e63a425657295239737f7ecd125f3"},
|
||||||
|
@ -14,6 +14,7 @@ itsdangerous = "^2.0.1"
|
|||||||
Authlib = "^0.15.4"
|
Authlib = "^0.15.4"
|
||||||
httpx = "^0.18.1"
|
httpx = "^0.18.1"
|
||||||
aioredis = "^1.3.1"
|
aioredis = "^1.3.1"
|
||||||
|
humanize = "^3.7.1"
|
||||||
|
|
||||||
[tool.poetry.dev-dependencies]
|
[tool.poetry.dev-dependencies]
|
||||||
black = "^21.6b0"
|
black = "^21.6b0"
|
||||||
|
@ -7,8 +7,22 @@
|
|||||||
Hello, {{ user.preferred_username }}
|
Hello, {{ user.preferred_username }}
|
||||||
<small>(<a href="{{ url_for('logout') }}">logout</a>)</small>
|
<small>(<a href="{{ url_for('logout') }}">logout</a>)</small>
|
||||||
</p>
|
</p>
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<th>Link</th>
|
||||||
|
<th>Validity </th>
|
||||||
|
<th>Operations</th>
|
||||||
|
</tr>
|
||||||
|
{% for invite in invites %}
|
||||||
|
<tr>
|
||||||
|
<td> <a class="invite" href="{{ url_for('home') }}{{ invite.link }}">{{ url_for('home') }}{{ invite.link }}</a> </td>
|
||||||
|
<td> {{ invite.human_time }} </td>
|
||||||
|
<td> <a href="#">copy</a> <a href="{{ url_for('invite_keycloak_delete') }}?invite={{ invite.link }}">delete</a> </td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</table>
|
||||||
<p>
|
<p>
|
||||||
<a href="{{ url_for('invite_keycloak') }}">Generate an invite link</a>
|
<a href="{{ url_for('invite_keycloak_create') }}">Generate an invite link</a>
|
||||||
</p>
|
</p>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
Loading…
Reference in New Issue
Block a user