Add user id to products model and apis
Browse files- api/evidence.py +1 -1
- models.py +4 -0
- templates/products.html +8 -0
- web/products.py +14 -6
- web/routes.py +10 -2
api/evidence.py
CHANGED
|
@@ -682,7 +682,7 @@ def finish_attestation():
|
|
| 682 |
from web.products import update_product_data
|
| 683 |
product_key = attestation.product_key
|
| 684 |
product_version = attestation.product_version
|
| 685 |
-
update_product_data(product_key, product_version)
|
| 686 |
|
| 687 |
# Return response matching swagger spec
|
| 688 |
return jsonify({
|
|
|
|
| 682 |
from web.products import update_product_data
|
| 683 |
product_key = attestation.product_key
|
| 684 |
product_version = attestation.product_version
|
| 685 |
+
update_product_data(product_key, product_version, user_id=attestation.user_id)
|
| 686 |
|
| 687 |
# Return response matching swagger spec
|
| 688 |
return jsonify({
|
models.py
CHANGED
|
@@ -386,6 +386,7 @@ class Product(db.Model):
|
|
| 386 |
id = db.Column(Integer, primary_key=True)
|
| 387 |
product_key = db.Column(String(255), nullable=False)
|
| 388 |
product_version = db.Column(String(255), nullable=False)
|
|
|
|
| 389 |
name = db.Column(String(255), nullable=True)
|
| 390 |
description = db.Column(Text, nullable=True)
|
| 391 |
product_metadata = db.Column(MutableDict.as_mutable(JSON), nullable=True)
|
|
@@ -394,6 +395,8 @@ class Product(db.Model):
|
|
| 394 |
updated_at = db.Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
|
| 395 |
deleted = db.Column(Boolean, default=False)
|
| 396 |
|
|
|
|
|
|
|
| 397 |
__table_args__ = (
|
| 398 |
db.UniqueConstraint('product_key', 'product_version', name='uq_product_key_version'),
|
| 399 |
)
|
|
@@ -403,6 +406,7 @@ class Product(db.Model):
|
|
| 403 |
'id': self.id,
|
| 404 |
'product_key': self.product_key,
|
| 405 |
'product_version': self.product_version,
|
|
|
|
| 406 |
'name': self.name,
|
| 407 |
'description': self.description,
|
| 408 |
'product_metadata': self.product_metadata,
|
|
|
|
| 386 |
id = db.Column(Integer, primary_key=True)
|
| 387 |
product_key = db.Column(String(255), nullable=False)
|
| 388 |
product_version = db.Column(String(255), nullable=False)
|
| 389 |
+
user_id = db.Column(Integer, ForeignKey('users.id'), nullable=False)
|
| 390 |
name = db.Column(String(255), nullable=True)
|
| 391 |
description = db.Column(Text, nullable=True)
|
| 392 |
product_metadata = db.Column(MutableDict.as_mutable(JSON), nullable=True)
|
|
|
|
| 395 |
updated_at = db.Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
|
| 396 |
deleted = db.Column(Boolean, default=False)
|
| 397 |
|
| 398 |
+
user = relationship("User", backref="products")
|
| 399 |
+
|
| 400 |
__table_args__ = (
|
| 401 |
db.UniqueConstraint('product_key', 'product_version', name='uq_product_key_version'),
|
| 402 |
)
|
|
|
|
| 406 |
'id': self.id,
|
| 407 |
'product_key': self.product_key,
|
| 408 |
'product_version': self.product_version,
|
| 409 |
+
'user_id': self.user_id,
|
| 410 |
'name': self.name,
|
| 411 |
'description': self.description,
|
| 412 |
'product_metadata': self.product_metadata,
|
templates/products.html
CHANGED
|
@@ -22,6 +22,14 @@
|
|
| 22 |
<div class="col-md-4">
|
| 23 |
<input type="text" class="form-control" name="filter" placeholder="Products substring" value="{{ filter_query }}">
|
| 24 |
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 25 |
<div class="col-md-2">
|
| 26 |
<button type="submit" class="btn btn-primary w-100">
|
| 27 |
<i data-feather="filter" class="me-1"></i> Filter
|
|
|
|
| 22 |
<div class="col-md-4">
|
| 23 |
<input type="text" class="form-control" name="filter" placeholder="Products substring" value="{{ filter_query }}">
|
| 24 |
</div>
|
| 25 |
+
{% if is_admin %}
|
| 26 |
+
<div class="col-md-3 form-check align-items-center d-flex">
|
| 27 |
+
<input class="form-check-input me-2" type="checkbox" id="showAllCheckbox" name="show_all" value="1" {% if show_all %}checked{% endif %} onchange="this.form.submit()">
|
| 28 |
+
<label class="form-check-label" for="showAllCheckbox">
|
| 29 |
+
Show all users' products
|
| 30 |
+
</label>
|
| 31 |
+
</div>
|
| 32 |
+
{% endif %}
|
| 33 |
<div class="col-md-2">
|
| 34 |
<button type="submit" class="btn btn-primary w-100">
|
| 35 |
<i data-feather="filter" class="me-1"></i> Filter
|
web/products.py
CHANGED
|
@@ -1,10 +1,12 @@
|
|
| 1 |
-
from flask import Blueprint, render_template, request, redirect, url_for
|
| 2 |
from models import db, Attestation, PolicyResult, Product
|
| 3 |
from sqlalchemy import func, text
|
| 4 |
|
| 5 |
-
def get_products_with_stats(filter_query=None):
|
| 6 |
# Only consume data from products table
|
| 7 |
query = Product.query.filter(Product.deleted == False)
|
|
|
|
|
|
|
| 8 |
if filter_query:
|
| 9 |
like_pattern = f'%{filter_query}%'
|
| 10 |
query = query.filter(
|
|
@@ -42,16 +44,22 @@ def get_products_with_stats(filter_query=None):
|
|
| 42 |
'attestation_count': attestation_count,
|
| 43 |
'policy_result_count': policy_result_count,
|
| 44 |
'badges': badges,
|
| 45 |
-
'product_metadata': product.product_metadata
|
|
|
|
| 46 |
})
|
| 47 |
return products, pagination
|
| 48 |
return products
|
| 49 |
|
| 50 |
# Function to update product data
|
| 51 |
-
def update_product_data(product_key, product_version, name=None, description=None, metadata=None, badges=None):
|
| 52 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 53 |
if not product:
|
| 54 |
-
product = Product(product_key=product_key, product_version=product_version)
|
| 55 |
db.session.add(product)
|
| 56 |
if name is not None:
|
| 57 |
product.name = name
|
|
|
|
| 1 |
+
from flask import Blueprint, render_template, request, redirect, url_for, session
|
| 2 |
from models import db, Attestation, PolicyResult, Product
|
| 3 |
from sqlalchemy import func, text
|
| 4 |
|
| 5 |
+
def get_products_with_stats(filter_query=None, user_id=None, show_all=False):
|
| 6 |
# Only consume data from products table
|
| 7 |
query = Product.query.filter(Product.deleted == False)
|
| 8 |
+
if not show_all and user_id is not None:
|
| 9 |
+
query = query.filter(Product.user_id == user_id)
|
| 10 |
if filter_query:
|
| 11 |
like_pattern = f'%{filter_query}%'
|
| 12 |
query = query.filter(
|
|
|
|
| 44 |
'attestation_count': attestation_count,
|
| 45 |
'policy_result_count': policy_result_count,
|
| 46 |
'badges': badges,
|
| 47 |
+
'product_metadata': product.product_metadata,
|
| 48 |
+
'user_id': product.user_id
|
| 49 |
})
|
| 50 |
return products, pagination
|
| 51 |
return products
|
| 52 |
|
| 53 |
# Function to update product data
|
| 54 |
+
def update_product_data(product_key, product_version, name=None, description=None, metadata=None, badges=None, user_id=None):
|
| 55 |
+
# Allow user_id to be passed explicitly (for background/API use), else fallback to session
|
| 56 |
+
if user_id is None:
|
| 57 |
+
user_id = session.get('user_id')
|
| 58 |
+
if user_id is None:
|
| 59 |
+
raise ValueError("user_id must be provided to update_product_data")
|
| 60 |
+
product = Product.query.filter_by(product_key=product_key, product_version=product_version, deleted=False, user_id=user_id).first()
|
| 61 |
if not product:
|
| 62 |
+
product = Product(product_key=product_key, product_version=product_version, user_id=user_id)
|
| 63 |
db.session.add(product)
|
| 64 |
if name is not None:
|
| 65 |
product.name = name
|
web/routes.py
CHANGED
|
@@ -225,8 +225,16 @@ def products_page():
|
|
| 225 |
filter_query = request.args.get('filter', '')
|
| 226 |
page = request.args.get('page', 1, type=int)
|
| 227 |
per_page = request.args.get('per_page', 20, type=int)
|
| 228 |
-
|
| 229 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 230 |
|
| 231 |
# --- Products CSV Download ---
|
| 232 |
@web_bp.route('/products/download-csv')
|
|
|
|
| 225 |
filter_query = request.args.get('filter', '')
|
| 226 |
page = request.args.get('page', 1, type=int)
|
| 227 |
per_page = request.args.get('per_page', 20, type=int)
|
| 228 |
+
user_id = session.get('user_id')
|
| 229 |
+
show_all = False
|
| 230 |
+
is_admin = False
|
| 231 |
+
if user_id:
|
| 232 |
+
from .routes import is_admin_user_web as _is_admin_user_web
|
| 233 |
+
is_admin = _is_admin_user_web(user_id)
|
| 234 |
+
if is_admin:
|
| 235 |
+
show_all = request.args.get('show_all', '0') == '1'
|
| 236 |
+
products, pagination = get_products_with_stats(filter_query, user_id=user_id, show_all=show_all)
|
| 237 |
+
return render_template('products.html', products=products, pagination=pagination, filter_query=filter_query, show_all=show_all, is_admin=is_admin)
|
| 238 |
|
| 239 |
# --- Products CSV Download ---
|
| 240 |
@web_bp.route('/products/download-csv')
|