feat: admins only feature flag

This commit is contained in:
decentral1se 2023-04-17 18:27:23 +02:00
parent 2835682455
commit bae57efaa6
No known key found for this signature in database
GPG Key ID: 03789458B3D0C410
4 changed files with 61 additions and 2 deletions

1
.gitignore vendored
View File

@ -1,2 +1,3 @@
*.pyc *.pyc
.env
/__pycache__/ /__pycache__/

View File

@ -27,6 +27,7 @@ No Masters edition of Keycloak.
- They are valid for 30 days by default (configurable via `INVITE_TIME_LIMIT`) - They are valid for 30 days by default (configurable via `INVITE_TIME_LIMIT`)
- Anyone with an invite link can create an account on the Keycloak, so don't share publicly! - Anyone with an invite link can create an account on the Keycloak, so don't share publicly!
- There is no access granularity on the account creation implemented yet, so the accounts are "global" - There is no access granularity on the account creation implemented yet, so the accounts are "global"
- **New**: it is possible to only allow "admins" to log in, see [feature flags](#feature-flags)
- Once the user fills in their name, email, password they will receive an email verification mail - Once the user fills in their name, email, password they will receive an email verification mail
If you want a feature implemented, please open an issue to discuss. If you want a feature implemented, please open an issue to discuss.
@ -60,6 +61,32 @@ your technology stack.
- Log in with your usual login details - Log in with your usual login details
- Follow the instructions on the web page to perform administrative actions - Follow the instructions on the web page to perform administrative actions
## Feature Flags
### Only admins can log in
#### Keycloak
- Create a new group under `Groups` called `Administrators` (case sensistive!)
- Create a new scope under `Client scopes`
- Name: `groups`
- Type: `Optional`
- Include in token scope: `yes`
- Under the `Mappers` tab of this client scope, choose `Add mapper`
- Mapper type/Name: `Groups Membership`
- Token claim name: `groups`
- Add to ID token: `yes`
- Add to access token: `yes`
- Add to userinfo: `yes`
- Add this client scope to your `admin-cli` client as `Optional`
- Add a test user to this group under `Users`
#### Keycloak Community Portal
- Set `FEATURE_FLAG_ADMINS_ONLY=True` in your `.env`
- You may want to customise `KEYCLOAK_GROUPS_KEY` / `KEYCLOAK_ADMINS_GROUP` if
you changed the value of `groups` / `Administrators` above
## Hacking ## Hacking
It's a [FastAPI](https://fastapi.tiangolo.com/) application (if you know It's a [FastAPI](https://fastapi.tiangolo.com/) application (if you know

View File

@ -12,7 +12,9 @@ KEYCLOAK_CLIENT_ID = environ.get("KEYCLOAK_CLIENT_ID")
KEYCLOAK_CLIENT_SECRET = environ.get("KEYCLOAK_CLIENT_SECRET") KEYCLOAK_CLIENT_SECRET = environ.get("KEYCLOAK_CLIENT_SECRET")
KEYCLOAK_DOMAIN = environ.get("KEYCLOAK_DOMAIN") KEYCLOAK_DOMAIN = environ.get("KEYCLOAK_DOMAIN")
KEYCLOAK_REALM = environ.get("KEYCLOAK_REALM") KEYCLOAK_REALM = environ.get("KEYCLOAK_REALM")
KEYCLOAK_SCOPES = environ.get("KEYCLOAK_SCOPES", "openid profile email") KEYCLOAK_SCOPES = environ.get("KEYCLOAK_SCOPES", "openid profile email groups")
KEYCLOAK_GROUPS_KEY = environ.get("KEYCLOAK_GROUPS_KEY", "groups")
KEYCLOAK_ADMINS_GROUP = environ.get("KEYCLOAK_ADMINS_GROUP", "Administrators")
KEYCLOAK_BASE_URL = f"https://{KEYCLOAK_DOMAIN}/realms/{KEYCLOAK_REALM}/protocol/openid-connect" # noqa KEYCLOAK_BASE_URL = f"https://{KEYCLOAK_DOMAIN}/realms/{KEYCLOAK_REALM}/protocol/openid-connect" # noqa
# Redis connection details, our main storage # Redis connection details, our main storage
@ -39,5 +41,15 @@ elif LOG_LEVEL == "debug":
else: else:
APP_LOG_LEVEL = logging.INFO APP_LOG_LEVEL = logging.INFO
def to_bool(env_var):
"""Parse a bool from the environment."""
return environ.get(env_var, "False").lower() in ("true", "1", "t")
# 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 = to_bool("AUTOMATICALLY_LOG_IN")
# Feature flags
# Only admins can log in to the interface
FEATURE_FLAG_ADMINS_ONLY = to_bool("FEATURE_FLAG_ADMINS_ONLY")

View File

@ -15,7 +15,26 @@ router = APIRouter()
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)
): ):
from keycloak_collective_portal.config import (
FEATURE_FLAG_ADMINS_ONLY,
KEYCLOAK_ADMINS_GROUP,
KEYCLOAK_GROUPS_KEY,
)
context = {"request": request, "user": user, "invites": invites} context = {"request": request, "user": user, "invites": invites}
if FEATURE_FLAG_ADMINS_ONLY:
context["message"] = "only admins can access this service"
if KEYCLOAK_GROUPS_KEY not in user:
return request.app.state.templates.TemplateResponse(
"invalid.html", context=context
)
if KEYCLOAK_ADMINS_GROUP not in user[KEYCLOAK_GROUPS_KEY]:
return request.app.state.templates.TemplateResponse(
"invalid.html", context=context
)
return request.app.state.templates.TemplateResponse( return request.app.state.templates.TemplateResponse(
"admin.html", context=context "admin.html", context=context
) )