Fix more foreing key usages
	
		
			
	
		
	
	
		
	
		
			All checks were successful
		
		
	
	
		
			
				
	
				ci/woodpecker/manual/woodpecker Pipeline was successful
				
			
		
		
	
	
				
					
				
			
		
			All checks were successful
		
		
	
	ci/woodpecker/manual/woodpecker Pipeline was successful
				
			Also refactors user info to class
This commit is contained in:
		@@ -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},
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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:
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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>
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user