Compare commits

...

3 Commits

Author SHA1 Message Date
c3831e9efe
routes/home: handle missing groups 2022-09-03 15:29:54 +10:00
860dbe6032
docs: add readme 2022-09-03 15:29:54 +10:00
aa86f5de48
routes/home: configure brand name 2022-09-03 15:29:51 +10:00
4 changed files with 49 additions and 7 deletions

37
README.md Normal file
View File

@ -0,0 +1,37 @@
# frontpage (name pending)
The front page of your self-hosted server.
This app fits the use case of having multiple applications with access gated by
an OIDC provider, and showing a user what applications they have access to.
## Usage
```sh
frontpage -c CONFIG.TOML
```
where a minimal config file looks like:
```toml
[oidc]
client_id = "some_id"
client_secret = "some_secret"
issuer = "https://auth.example.com/oauth"
scopes = [ "groups" ]
```
Applications are defined using the `apps` keys:
```toml
[apps.login]
name = "Login portal"
url = "https://auth.example.com"
description = "Update your user details"
groups = [ "users" ]
```
In this example, only users whose OIDC groups claim includes `users` will be
allowed to see a link to the login portal. Protection of the link, should a user
gain access to it otherwise, is expected to be done externall (e.g., via an
ingress controller).

View File

@ -15,6 +15,7 @@ class CoreConfig:
debug: bool = False debug: bool = False
port: int = 5000 port: int = 5000
name: str = "Front page"
@dataclass @dataclass
@ -43,8 +44,8 @@ class AppConfig:
class Config: class Config:
"""Top-level configuration.""" """Top-level configuration."""
core: CoreConfig core: CoreConfig = field(default_factory=CoreConfig)
oidc: OidcConfig oidc: OidcConfig = field(default_factory=OidcConfig)
apps: Dict[str, AppConfig] = field(default_factory=dict) apps: Dict[str, AppConfig] = field(default_factory=dict)

View File

@ -7,7 +7,7 @@ from flask import Blueprint, current_app, render_template
from flask_pyoidc import OIDCAuthentication from flask_pyoidc import OIDCAuthentication
from flask_pyoidc.user_session import UserSession from flask_pyoidc.user_session import UserSession
from frontpage.config import AppConfig, current_config from frontpage.config import AppConfig, Config, current_config
def _allowed(items_from: Iterable[Any], items_in: Iterable[Any]) -> bool: def _allowed(items_from: Iterable[Any], items_in: Iterable[Any]) -> bool:
@ -29,12 +29,16 @@ def register(auth: OIDCAuthentication, auth_provider: str) -> Blueprint:
Renders the home route. Renders the home route.
""" """
user_session = UserSession(flask.session) user_session = UserSession(flask.session)
groups: List[str] = user_session.userinfo["groups"] groups: List[str] = user_session.userinfo.get("groups") or []
apps: AppConfig = current_config().apps config: Config = current_config()
name = config.core.name
apps = config.apps
allowed_apps = { allowed_apps = {
ident: a for ident, a in apps.items() if _allowed(a.groups, groups) ident: a for ident, a in apps.items() if _allowed(a.groups, groups)
} }
return render_template("home.html", apps=allowed_apps, groups=groups) return render_template(
"home.html", brand_name=name, apps=allowed_apps, groups=groups
)
return routes return routes

View File

@ -8,7 +8,7 @@
<body> <body>
<nav class="nav"> <nav class="nav">
<div class="nav-left"> <div class="nav-left">
<a class="brand" href="/">Front page</a> <a class="brand" href="/">{{ brand_name }}</a>
</div> </div>
</nav> </nav>
<main class="container"> <main class="container">