Spaces:
Paused
Paused
Update app.py
Browse files
app.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
| 1 |
|
| 2 |
-
from flask import Flask, render_template_string, request, redirect, url_for, send_file, flash, jsonify
|
| 3 |
import json
|
| 4 |
import os
|
| 5 |
import logging
|
|
@@ -44,6 +44,24 @@ STATUS_MAP_RU = {
|
|
| 44 |
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
|
| 45 |
|
| 46 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 47 |
|
| 48 |
def download_db_from_hf(specific_file=None, retries=DOWNLOAD_RETRIES, delay=DOWNLOAD_DELAY):
|
| 49 |
if not HF_TOKEN_READ and not HF_TOKEN_WRITE:
|
|
@@ -1590,7 +1608,6 @@ def product_detail(index):
|
|
| 1590 |
logging.warning(f"Attempted access to non-existent or out-of-stock product with index {index}")
|
| 1591 |
return "Товар не найден или отсутствует в наличии.", 404
|
| 1592 |
|
| 1593 |
-
# Pass the sorted index back so the JS function can correctly call openQuantityModal
|
| 1594 |
products_index = index
|
| 1595 |
|
| 1596 |
return render_template_string(
|
|
@@ -1632,7 +1649,7 @@ def create_order():
|
|
| 1632 |
"price": price,
|
| 1633 |
"quantity": quantity,
|
| 1634 |
"color": item.get('color', 'N/A'),
|
| 1635 |
-
"model": item.get('model', 'N/A'),
|
| 1636 |
"photo": photo_name,
|
| 1637 |
"photo_url": photo_url
|
| 1638 |
})
|
|
@@ -1771,7 +1788,7 @@ def admin():
|
|
| 1771 |
category = request.form.get('category')
|
| 1772 |
photos_files = request.files.getlist('photos')
|
| 1773 |
colors = [c.strip() for c in request.form.getlist('colors') if c.strip()]
|
| 1774 |
-
models = [m.strip() for m in request.form.getlist('models') if m.strip()]
|
| 1775 |
in_stock = 'in_stock' in request.form
|
| 1776 |
is_top = 'is_top' in request.form
|
| 1777 |
|
|
@@ -1844,7 +1861,7 @@ def admin():
|
|
| 1844 |
'id': str(uuid.uuid4()),
|
| 1845 |
'name': name, 'price': price, 'description': description,
|
| 1846 |
'category': category if category in categories else 'Без категории',
|
| 1847 |
-
'photos': photos_list, 'colors': colors, 'models': models,
|
| 1848 |
'in_stock': in_stock, 'is_top': is_top
|
| 1849 |
}
|
| 1850 |
products.append(new_product)
|
|
@@ -1879,7 +1896,7 @@ def admin():
|
|
| 1879 |
category = request.form.get('category')
|
| 1880 |
product_to_edit['category'] = category if category in categories else 'Без категории'
|
| 1881 |
product_to_edit['colors'] = [c.strip() for c in request.form.getlist('colors') if c.strip()]
|
| 1882 |
-
product_to_edit['models'] = [m.strip() for m in request.form.getlist('models') if m.strip()]
|
| 1883 |
product_to_edit['in_stock'] = 'in_stock' in request.form
|
| 1884 |
product_to_edit['is_top'] = 'is_top' in request.form
|
| 1885 |
|
|
|
|
| 1 |
|
| 2 |
+
from flask import Flask, render_template_string, request, redirect, url_for, send_file, flash, jsonify, Response
|
| 3 |
import json
|
| 4 |
import os
|
| 5 |
import logging
|
|
|
|
| 44 |
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
|
| 45 |
|
| 46 |
|
| 47 |
+
@app.after_request
|
| 48 |
+
def add_security_headers(response):
|
| 49 |
+
csp = (
|
| 50 |
+
"default-src 'self'; "
|
| 51 |
+
"script-src 'self' https://cdnjs.cloudflare.com; "
|
| 52 |
+
"style-src 'self' 'unsafe-inline' https://cdnjs.cloudflare.com https://fonts.googleapis.com; "
|
| 53 |
+
"font-src 'self' https://cdnjs.cloudflare.com https://fonts.gstatic.com; "
|
| 54 |
+
"img-src 'self' data: https://huggingface.co https://via.placeholder.com; "
|
| 55 |
+
"object-src 'none'; "
|
| 56 |
+
"frame-ancestors 'none'; "
|
| 57 |
+
"base-uri 'self';"
|
| 58 |
+
)
|
| 59 |
+
response.headers['Content-Security-Policy'] = csp
|
| 60 |
+
response.headers['Strict-Transport-Security'] = 'max-age=31536000; includeSubDomains'
|
| 61 |
+
response.headers['X-Content-Type-Options'] = 'nosniff'
|
| 62 |
+
response.headers['X-Frame-Options'] = 'SAMEORIGIN'
|
| 63 |
+
response.headers['Referrer-Policy'] = 'strict-origin-when-cross-origin'
|
| 64 |
+
return response
|
| 65 |
|
| 66 |
def download_db_from_hf(specific_file=None, retries=DOWNLOAD_RETRIES, delay=DOWNLOAD_DELAY):
|
| 67 |
if not HF_TOKEN_READ and not HF_TOKEN_WRITE:
|
|
|
|
| 1608 |
logging.warning(f"Attempted access to non-existent or out-of-stock product with index {index}")
|
| 1609 |
return "Товар не найден или отсутствует в наличии.", 404
|
| 1610 |
|
|
|
|
| 1611 |
products_index = index
|
| 1612 |
|
| 1613 |
return render_template_string(
|
|
|
|
| 1649 |
"price": price,
|
| 1650 |
"quantity": quantity,
|
| 1651 |
"color": item.get('color', 'N/A'),
|
| 1652 |
+
"model": item.get('model', 'N/A'),
|
| 1653 |
"photo": photo_name,
|
| 1654 |
"photo_url": photo_url
|
| 1655 |
})
|
|
|
|
| 1788 |
category = request.form.get('category')
|
| 1789 |
photos_files = request.files.getlist('photos')
|
| 1790 |
colors = [c.strip() for c in request.form.getlist('colors') if c.strip()]
|
| 1791 |
+
models = [m.strip() for m in request.form.getlist('models') if m.strip()]
|
| 1792 |
in_stock = 'in_stock' in request.form
|
| 1793 |
is_top = 'is_top' in request.form
|
| 1794 |
|
|
|
|
| 1861 |
'id': str(uuid.uuid4()),
|
| 1862 |
'name': name, 'price': price, 'description': description,
|
| 1863 |
'category': category if category in categories else 'Без категории',
|
| 1864 |
+
'photos': photos_list, 'colors': colors, 'models': models,
|
| 1865 |
'in_stock': in_stock, 'is_top': is_top
|
| 1866 |
}
|
| 1867 |
products.append(new_product)
|
|
|
|
| 1896 |
category = request.form.get('category')
|
| 1897 |
product_to_edit['category'] = category if category in categories else 'Без категории'
|
| 1898 |
product_to_edit['colors'] = [c.strip() for c in request.form.getlist('colors') if c.strip()]
|
| 1899 |
+
product_to_edit['models'] = [m.strip() for m in request.form.getlist('models') if m.strip()]
|
| 1900 |
product_to_edit['in_stock'] = 'in_stock' in request.form
|
| 1901 |
product_to_edit['is_top'] = 'is_top' in request.form
|
| 1902 |
|