Fix more foreing key usages
All checks were successful
ci/woodpecker/manual/woodpecker Pipeline was successful

Also refactors user info to class
This commit is contained in:
Madis Mägi 2023-08-06 05:43:47 +03:00
parent a637c2d2a1
commit c8b09d54f8
6 changed files with 56 additions and 51 deletions

View File

@ -32,24 +32,17 @@ def view_users():
@page_api.route("/cards", methods=["POST"]) @page_api.route("/cards", methods=["POST"])
@check_api_key @check_api_key
def get_group_cards(): def get_group_cards():
groups = request.json.get("groups", False) request_groups = request.json.get("groups", False)
if not groups: if not request_groups:
return "must specify groups in parameter", 400 return "must specify groups in parameter", 400
print(f"groups requested are: {groups}") print(f"groups requested are: {request_groups}")
print(f"found users: {users}") print(f"found users: {users}")
gu = [] keys = []
for u in users: for u in users:
for gr in u["status"]["groups"]: for group in u.groups:
group_name = f"{gr['prefix']}:{gr['name']}" if group in request_groups:
print(f"prefix is {gr['prefix']}") keys.append(u.username)
print(f"name is {gr['name']}") break
print(f"group name is {group_name}")
for group in groups:
print(f"checking {group}")
if group_name == group:
gu.append(u)
print(f"gu is: {gu}")
keys = list(map(lambda u: u["metadata"]["name"], gu))
print(f"keys are {keys}") print(f"keys are {keys}")
flt = { flt = {
"token.uid_hash": {"$exists": True}, "token.uid_hash": {"$exists": True},

View File

@ -8,6 +8,8 @@ from flask import g, request
from flask_wtf import FlaskForm from flask_wtf import FlaskForm
from pymongo import MongoClient from pymongo import MongoClient
from kubernetes import client, config from kubernetes import client, config
from typing import List
from dataclasses import dataclass, field
import const import const
@ -16,14 +18,30 @@ OIDC_USERS_NAMESPACE = os.getenv("OIDC_USERS_NAMESPACE")
db = MongoClient(const.MONGO_URI).get_default_database() db = MongoClient(const.MONGO_URI).get_default_database()
@dataclass
class User:
username: str = None
display_name: str = None
groups: List[str] = field(default_factory=list)
def __getitem__(self, item):
return getattr(self, item)
def get_users(): def get_users():
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")
return ret["items"] for item in ret["items"]:
username = item['metadata']['name']
display_name = item.get("spec", {}).get("customProfile", {}).get("name", None)
groups = []
for group in item.get("status", {}).get("groups", []):
groups.append(f"{group['prefix']}:{group['name']}")
yield User(username, display_name, groups)
users = get_users() users = list(get_users())
users_lookup = {u['metadata']['name'] : u for u in users} users_lookup = {u.username : u for u in users}
class CustomForm(FlaskForm): class CustomForm(FlaskForm):
# quite hacky # quite hacky
@ -90,7 +108,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, {}).get("spec", {}).get("customProfile", {}).get("name", u)} for u in results] results = [{"username": u, "display_name": 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

@ -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 from common import CustomForm, build_query, flatten, format_name, spam, users_lookup
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__)
@ -29,16 +29,10 @@ def view_inventory_view(item_id):
photo_url = "%s/kspace-inventory/%s" % (base_url, item_id) photo_url = "%s/kspace-inventory/%s" % (base_url, item_id)
return render_template(template , **locals()) return render_template(template , **locals())
def fetch_members_select(existing_id=None): def fetch_members_select():
q = [{"enabled": True}]
if existing_id:
q.append({"_id": ObjectId(existing_id)})
objs = db.member.find(filter = { "$or": q }, projection = {
"full_name": 1
}).sort("full_name", 1)
choices = [(None, None)] choices = [(None, None)]
for obj in objs: for username, user in users_lookup.items():
choices.append((obj["_id"], obj["full_name"])) choices.append((username, user.display_name or username))
choices = list(set(choices)) choices = list(set(choices))
return choices return choices
@ -54,10 +48,10 @@ def setup_user_select(select_field, name_fields):
existing_id = None existing_id = None
if select_field.data and select_field.data != 'None': if select_field.data and select_field.data != 'None':
existing_id = select_field.data existing_id = select_field.data
select_field.choices = fetch_members_select(existing_id) select_field.choices = fetch_members_select()
if existing_id: if existing_id:
values = dict(select_field.choices) values = dict(select_field.choices)
value = values.get(ObjectId(existing_id)) value = values.get(existing_id)
for name_field in name_fields: for name_field in name_fields:
name_field.data = value name_field.data = value
@ -73,18 +67,18 @@ def setup_default_owner(select_field):
def member_select_coerce(x): def member_select_coerce(x):
x = str(x) x = str(x)
if x and x != "None": if x and x != "None":
return ObjectId(x) return x
else: else:
return None return None
class MemberForm(Form): class MemberForm(Form):
label = None label = None
foreign_id = SelectField(choices=[], coerce=member_select_coerce) username = SelectField(choices=[], coerce=member_select_coerce)
display_name = StringField() display_name = StringField()
def __init__(self, label=None, *args, **kwargs): def __init__(self, label=None, *args, **kwargs):
super(MemberForm, self).__init__(*args, **kwargs) super(MemberForm, self).__init__(*args, **kwargs)
self.label = label self.label = label
setup_user_select(self.foreign_id, [self.display_name]) setup_user_select(self.username, [self.display_name])
class InventoryForm(Form): class InventoryForm(Form):
owner = FormField(MemberForm, label="Owner") owner = FormField(MemberForm, label="Owner")
@ -112,7 +106,7 @@ class InventoryItemForm(CustomForm):
_description_placeholder = "Insert Markdown here." _description_placeholder = "Insert Markdown here."
description = TextAreaField('Description', [validators.optional(), validators.length(max=3000)], render_kw={"placeholder": _description_placeholder}) description = TextAreaField('Description', [validators.optional(), validators.length(max=3000)], render_kw={"placeholder": _description_placeholder})
def setup_defaults_add(self): def setup_defaults_add(self):
setup_default_owner(self.inventory.form.owner.form.foreign_id) setup_default_owner(self.inventory.form.owner.form.username)
self.inventory.form.public.render_kw = {"checked": "checked"} self.inventory.form.public.render_kw = {"checked": "checked"}
self.inventory.form.public.data = "y" self.inventory.form.public.data = "y"
@ -190,10 +184,10 @@ def save_inventory_item(item_id=None, **_):
if not d["shortener"]["slug"]: if not d["shortener"]["slug"]:
d.pop("shortener") d.pop("shortener")
if "user" in d["inventory"]: if "user" in d["inventory"]:
if not d["inventory"]["user"]["foreign_id"]: if not d["inventory"]["user"]["username"]:
d["inventory"].pop("user") d["inventory"].pop("user")
if "owner" in d["inventory"]: if "owner" in d["inventory"]:
if not d["inventory"]["owner"]["foreign_id"]: if not d["inventory"]["owner"]["username"]:
d["inventory"].pop("owner") d["inventory"].pop("owner")
item_id = db.inventory.insert_one(d).inserted_id item_id = db.inventory.insert_one(d).inserted_id
except pymongo.errors.DuplicateKeyError: except pymongo.errors.DuplicateKeyError:
@ -402,7 +396,7 @@ def view_inventory_claim(item_id):
user = read_user() user = read_user()
db.inventory.update_one({ db.inventory.update_one({
"_id": ObjectId(item_id), "_id": ObjectId(item_id),
"inventory.owner.foreign_id": None "inventory.owner.username": None
}, { }, {
"$set": { "$set": {
"inventory.owner.username": user["username"], "inventory.owner.username": user["username"],
@ -419,7 +413,7 @@ def view_inventory_use(item_id):
item = db.inventory.find_one({ item = db.inventory.find_one({
"_id": ObjectId(item_id), "_id": ObjectId(item_id),
"inventory.usable": True, "inventory.usable": True,
"inventory.user.foreign_id": None "inventory.user.username": None
}) })
if not item: if not item:
return abort(404) return abort(404)

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 from common import CustomForm, devenv, flatten, format_name, spam, users_lookup, 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 api import page_api from api import page_api
@ -60,7 +60,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, {}).get("spec", {}).get("customProfile", {}).get("name", False) display_name = 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):
@ -82,16 +82,16 @@ def render_last_seen(machine, stale_minutes=30):
return Markup("opacity: 25%;") return Markup("opacity: 25%;")
def render_owner_link(item): def render_owner_link(item):
owner = item.get("inventory", {}).get("owner") username = item.get("inventory", {}).get("owner", {}).get("username", False)
if owner and owner.get("foreign_id") and owner.get("display_name"): if username:
return Markup("<a href=\"/m/user/%s\">%s</a>" % (owner["foreign_id"], owner["display_name"])) return Markup("<a href=\"/m/user/%s\">%s</a>" % (username, render_user_display_name(username)))
else: else:
return Markup("<form method=\"post\" action=\"/m/inventory/%s/claim\"><button type=\"submit\" class=\"waves-effect waves-light btn\">Mine!</button></form>" % (item["_id"])) return Markup("<form method=\"post\" action=\"/m/inventory/%s/claim\"><button type=\"submit\" class=\"waves-effect waves-light btn\">Mine!</button></form>" % (item["_id"]))
def render_user_link(item): def render_user_link(item):
user = item.get("inventory", {}).get("user") username = item.get("inventory", {}).get("user", {}).get("username", False)
if user and user.get("foreign_id") and user.get("display_name"): if username:
return Markup("<a href=\"/m/user/%s\">%s</a>" % (user["foreign_id"], user["display_name"])) return Markup("<a href=\"/m/user/%s\">%s</a>" % (username, render_user_display_name(username)))
elif item.get("inventory", {}).get("usable"): elif item.get("inventory", {}).get("usable"):
return Markup("<form method=\"post\" action=\"/m/inventory/%s/use\"><button type=\"submit\" class=\"waves-effect waves-light btn\">I use it now!</button></form>" % (item["_id"])) return Markup("<form method=\"post\" action=\"/m/inventory/%s/use\"><button type=\"submit\" class=\"waves-effect waves-light btn\">I use it now!</button></form>" % (item["_id"]))
else: else:

View File

@ -66,12 +66,12 @@
<tr> <tr>
<td>Owner</td> <td>Owner</td>
<td>{{ form.inventory.owner.foreign_id }}</td> <td>{{ form.inventory.owner.username }}</td>
</tr> </tr>
<tr> <tr>
<td>Current user</td> <td>Current user</td>
<td>{{ form.inventory.user.foreign_id }}</td> <td>{{ form.inventory.user.username }}</td>
</tr> </tr>
<tr> <tr>

View File

@ -16,8 +16,8 @@
{% for item in items %} {% for item in items %}
<tr> <tr>
<td>{{ item | format_name }} {{ item.comment }}</td> <td>{{ item | format_name }} {{ item.comment }}</td>
<td>{% if item.inventory.owner %}<a href="/m/user/{{ item.inventory.owner.foreign_id }}">{{ item.inventory.owner.username | display_name }}</a>{% endif %}</td> <td>{% if item.inventory.owner %}<a href="/m/user/{{ item.inventory.owner.username }}">{{ item.inventory.owner.username | display_name }}</a>{% endif %}</td>
<td>{% if item.inventory.user %}<a href="/m/user/{{ item.inventory.user.foreign_id }}">{{ item.inventory.user.username | display_name }}</a>{% endif %}</td> <td>{% if item.inventory.user %}<a href="/m/user/{{ item.inventory.user.username }}">{{ item.inventory.user.username | display_name }}</a>{% endif %}</td>
<td> <td>
<form action="/m/inventory/{{item._id}}/{{action_path}}/{{slug}}" method="get"> <form action="/m/inventory/{{item._id}}/{{action_path}}/{{slug}}" method="get">
<button class="waves-effect waves-light btn" type="submit">{{action_label}}</button> <button class="waves-effect waves-light btn" type="submit">{{action_label}}</button>