Put users lookup in request context

This commit is contained in:
Madis Mägi 2023-08-16 02:59:42 +03:00
parent e8060da3d6
commit 07772d9d42
5 changed files with 27 additions and 21 deletions

View File

@ -5,7 +5,7 @@ from datetime import datetime, timedelta
from functools import wraps from functools import wraps
from pymongo import MongoClient from pymongo import MongoClient
from flask import Blueprint, abort, g, make_response, redirect, render_template, request, jsonify from flask import Blueprint, abort, g, make_response, redirect, render_template, request, jsonify
from common import CustomForm, build_query, flatten, format_name, spam, users, User from common import CustomForm, build_query, flatten, format_name, spam, User
page_api = Blueprint("api", __name__) page_api = Blueprint("api", __name__)
db = MongoClient(const.MONGO_URI).get_default_database() db = MongoClient(const.MONGO_URI).get_default_database()
@ -26,7 +26,7 @@ def check_api_key(f):
@page_api.route("/users") @page_api.route("/users")
@check_api_key @check_api_key
def view_users(): def view_users():
resp = users resp = g.users
print(resp) print(resp)
return jsonify(resp) return jsonify(resp)
@ -37,9 +37,9 @@ def get_group_cards():
if not request_groups: if not request_groups:
return "must specify groups in parameter", 400 return "must specify groups in parameter", 400
print(f"groups requested are: {request_groups}") print(f"groups requested are: {request_groups}")
print(f"found users: {users}") print(f"found users: {g.users}")
keys = [] keys = []
for u in users: for u in g.users:
for group in u.groups: for group in u.groups:
if group in request_groups: if group in request_groups:
keys.append(u.username) keys.append(u.username)
@ -80,8 +80,8 @@ def view_slack_doorboy():
return "Invalid command was supplied" return "Invalid command was supplied"
member = None member = None
print(users) print(g.users)
for user in users: for user in g.users:
if user.slack_id == request.form.get("user_id"): if user.slack_id == request.form.get("user_id"):
member = user member = user

View File

@ -29,7 +29,7 @@ class User:
return getattr(self, item) return getattr(self, item)
def get_users(): def get_users_inner():
config.load_incluster_config() config.load_incluster_config()
api_instance = client.CustomObjectsApi() api_instance = client.CustomObjectsApi()
ret = api_instance.list_namespaced_custom_object("codemowers.io", "v1alpha1", OIDC_USERS_NAMESPACE, "oidcgatewayusers") ret = api_instance.list_namespaced_custom_object("codemowers.io", "v1alpha1", OIDC_USERS_NAMESPACE, "oidcgatewayusers")
@ -42,8 +42,10 @@ def get_users():
groups.append(f"{group['prefix']}:{group['name']}") groups.append(f"{group['prefix']}:{group['name']}")
yield User(username, display_name, slack_id, groups) yield User(username, display_name, slack_id, groups)
users = list(get_users()) def get_users():
users = list(get_users_inner())
users_lookup = {u.username : u for u in users} users_lookup = {u.username : u for u in users}
return users, users_lookup
class CustomForm(FlaskForm): class CustomForm(FlaskForm):
# quite hacky # quite hacky
@ -108,7 +110,7 @@ def build_query(base_query, fields=[], sort_fields={}):
val = request.args.get(key, type=tp) val = request.args.get(key, type=tp)
results = db.inventory.find(base_query).distinct(attr) results = db.inventory.find(base_query).distinct(attr)
if key in ("inventory_owner_username", "inventory_user_username"): if key in ("inventory_owner_username", "inventory_user_username"):
results = [{"username": u, "display_name": users_lookup.get(u, User()).display_name or u} for u in results] results = [{"username": u, "display_name": g.users_lookup.get(u, User()).display_name or u} for u in results]
results = sorted(results, key = lambda k: k["display_name"]) results = sorted(results, key = lambda k: k["display_name"])
elif tp != list: elif tp != list:
results = sorted(results) results = sorted(results)

View File

@ -10,7 +10,7 @@ from wtforms.validators import DataRequired
import pytz import pytz
import const import const
from common import spam, users_lookup, users, User from common import spam, User
from oidc import login_required, read_user from oidc import login_required, read_user
page_doorboy = Blueprint("doorboy", __name__) page_doorboy = Blueprint("doorboy", __name__)
@ -155,7 +155,7 @@ def view_doorboy_open(door):
access_group = "k-space:workshop" access_group = "k-space:workshop"
else: else:
access_group = "k-space:floor" access_group = "k-space:floor"
approved = access_group in users_lookup.get(user["username"], User()).groups approved = access_group in g.users_lookup.get(user["username"], User()).groups
db.eventlog.insert_one({ db.eventlog.insert_one({
"method": "web", "method": "web",
"approved": approved, "approved": approved,
@ -195,7 +195,7 @@ def view_doorboy_slam():
@login_required @login_required
def view_doorboy(): def view_doorboy():
user = read_user() user = read_user()
workshop_access = "k-space:workshop" in users_lookup.get(user["username"], User()).groups workshop_access = "k-space:workshop" in g.users_lookup.get(user["username"], User()).groups
latest_events = db.eventlog.find({"component": "doorboy", "type":"open-door"}).sort([("timestamp", -1)]).limit(10); latest_events = db.eventlog.find({"component": "doorboy", "type":"open-door"}).sort([("timestamp", -1)]).limit(10);
latest_swipes = db.inventory.find({"component": "doorboy", "type":"token"}).sort([("last_seen", -1)]).limit(10); latest_swipes = db.inventory.find({"component": "doorboy", "type":"token"}).sort([("last_seen", -1)]).limit(10);
return render_template("doorboy.html", **locals()) return render_template("doorboy.html", **locals())
@ -213,7 +213,7 @@ def view_own_cards():
def view_user_cards_inner(username): def view_user_cards_inner(username):
user = read_user() user = read_user()
subject_user = users_lookup.get(username) subject_user = g.users_lookup.get(username)
if not subject_user: if not subject_user:
return abort(404) return abort(404)
is_self = user["username"] == subject_user["username"] is_self = user["username"] == subject_user["username"]
@ -246,7 +246,7 @@ def view_doorboy_admin():
user_keyfobs = {r["_id"] : r["cards"] for r in results} user_keyfobs = {r["_id"] : r["cards"] for r in results}
orphaned_keyfobs = user_keyfobs.pop(None) orphaned_keyfobs = user_keyfobs.pop(None)
no_keyfobs = [u for u in users if not user_keyfobs.get(u.username)] no_keyfobs = [u for u in g.users if not user_keyfobs.get(u.username)]
last_seen = {key : max(datetime_handle(card.get("last_seen")) for card in value) for key, value in user_keyfobs.items()} last_seen = {key : max(datetime_handle(card.get("last_seen")) for card in value) for key, value in user_keyfobs.items()}
orphaned_keyfobs = sorted(orphaned_keyfobs, key = lambda o : (not bool(o.get("comment")), o.get("comment", ""))) orphaned_keyfobs = sorted(orphaned_keyfobs, key = lambda o : (not bool(o.get("comment")), o.get("comment", "")))
@ -350,8 +350,8 @@ def view_swipe():
status = "Permitted" if form["success"] else "Denied" status = "Permitted" if form["success"] else "Denied"
username = token.get("inventory", {}).get("owner", {}).get("username", None) username = token.get("inventory", {}).get("owner", {}).get("username", None)
if username and username in users_lookup: if username and username in g.users_lookup:
subject = users_lookup[username].display_name or username subject = g.users_lookup[username].display_name or username
else: else:
subject = "Unknown" subject = "Unknown"
msg = "%s %s door access for %s identified by keycard/keyfob" % (status, form["door"], subject) msg = "%s %s door access for %s identified by keycard/keyfob" % (status, form["door"], subject)

View File

@ -11,7 +11,7 @@ from wtforms.form import Form
from wtforms.validators import Length from wtforms.validators import Length
import const import const
from common import CustomForm, build_query, flatten, format_name, spam, users_lookup from common import CustomForm, build_query, flatten, format_name, spam
from oidc import page_oidc, login_required, read_user, do_login from oidc import page_oidc, login_required, read_user, do_login
page_inventory = Blueprint("inventory", __name__) page_inventory = Blueprint("inventory", __name__)
@ -31,7 +31,7 @@ def view_inventory_view(item_id):
def fetch_members_select(): def fetch_members_select():
choices = [(None, None)] choices = [(None, None)]
for username, user in users_lookup.items(): for username, user in g.users_lookup.items():
choices.append((username, user.display_name or username)) choices.append((username, user.display_name or username))
choices = list(set(choices)) choices = list(set(choices))
choices = sorted(choices, key = lambda k: k[1] or "") choices = sorted(choices, key = lambda k: k[1] or "")

View File

@ -44,7 +44,7 @@ from wtforms.form import Form
from wtforms.validators import DataRequired from wtforms.validators import DataRequired
import const import const
from common import CustomForm, devenv, flatten, format_name, spam, users_lookup, User from common import CustomForm, devenv, flatten, format_name, spam, get_users, User
from inventory import page_inventory from inventory import page_inventory
from oidc import page_oidc, login_required, read_user from oidc import page_oidc, login_required, read_user
from doorboy import page_doorboy from doorboy import page_doorboy
@ -61,7 +61,7 @@ def check_foreign_key_format(item):
def render_user_display_name(username): def render_user_display_name(username):
if not username: if not username:
return "" return ""
display_name = users_lookup.get(username, User()).display_name display_name = g.users_lookup.get(username, User()).display_name
return display_name or username return display_name or username
def render_markdown(text): def render_markdown(text):
@ -182,6 +182,10 @@ def dev_only(f):
return decorated_function return decorated_function
@app.before_request
def do_before_request():
g.users, g.users_lookup = get_users()
@app.context_processor @app.context_processor
def inject_context(): def inject_context():
return dict(devenv=devenv, inventory_assets_base_url=const.INVENTORY_ASSETS_BASE_URL, members_host=const.MEMBERS_HOST) return dict(devenv=devenv, inventory_assets_base_url=const.INVENTORY_ASSETS_BASE_URL, members_host=const.MEMBERS_HOST)