Fix
This commit is contained in:
parent
6f573999ef
commit
98bbc486e6
83
app.py
83
app.py
|
|
@ -16,10 +16,43 @@ def get_db_connection():
|
||||||
return conn
|
return conn
|
||||||
|
|
||||||
def is_valid_email(email):
|
def is_valid_email(email):
|
||||||
|
"""Проверяет корректность email адреса (только популярные почтовые домены)"""
|
||||||
if not email:
|
if not email:
|
||||||
return True
|
return True
|
||||||
pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.(ru|com)$'
|
|
||||||
return re.match(pattern, email.lower()) is not None
|
# Ограничение длины
|
||||||
|
if len(email) > 50:
|
||||||
|
return False
|
||||||
|
|
||||||
|
if '@' not in email:
|
||||||
|
return False
|
||||||
|
|
||||||
|
local_part = email.split('@')[0]
|
||||||
|
domain = email.split('@')[1].lower()
|
||||||
|
|
||||||
|
# Локальная часть: минимум 2 символа, не только цифры
|
||||||
|
if len(local_part) < 2 or len(local_part) > 30:
|
||||||
|
return False
|
||||||
|
|
||||||
|
if local_part.isdigit():
|
||||||
|
return False
|
||||||
|
|
||||||
|
if not local_part[0].isalpha():
|
||||||
|
return False
|
||||||
|
|
||||||
|
# Разрешенные почтовые домены
|
||||||
|
allowed_domains = [
|
||||||
|
'mail.ru', 'yandex.ru', 'gmail.com', 'gmail.ru',
|
||||||
|
'list.ru', 'bk.ru', 'inbox.ru', 'rambler.ru',
|
||||||
|
'ya.ru', 'google.com', 'outlook.com', 'hotmail.com',
|
||||||
|
'yahoo.com', 'protonmail.com', 'icloud.com'
|
||||||
|
]
|
||||||
|
|
||||||
|
# Проверяем, что домен есть в списке разрешенных
|
||||||
|
if domain not in allowed_domains:
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
def login_required(f):
|
def login_required(f):
|
||||||
@wraps(f)
|
@wraps(f)
|
||||||
|
|
@ -191,15 +224,18 @@ def register():
|
||||||
username = request.form['username']
|
username = request.form['username']
|
||||||
password = request.form['password']
|
password = request.form['password']
|
||||||
email = request.form.get('email', '')
|
email = request.form.get('email', '')
|
||||||
|
|
||||||
if email and not is_valid_email(email):
|
if email and not is_valid_email(email):
|
||||||
flash('Введите корректный email адрес (должен заканчиваться на .ru или .com)', 'danger')
|
flash('Введите корректный email адрес (допустимые домены: mail.ru, yandex.ru, gmail.com, list.ru, bk.ru, inbox.ru, rambler.ru, ya.ru, google.com, outlook.com, hotmail.com, yahoo.com, protonmail.com, icloud.com)', 'danger')
|
||||||
return redirect(url_for('register'))
|
return redirect(url_for('register'))
|
||||||
|
|
||||||
conn = get_db_connection()
|
conn = get_db_connection()
|
||||||
user = conn.execute('SELECT * FROM users WHERE username = ?', (username,)).fetchone()
|
user = conn.execute('SELECT * FROM users WHERE username = ?', (username,)).fetchone()
|
||||||
if user:
|
if user:
|
||||||
flash('Пользователь с таким именем уже существует', 'danger')
|
flash('Пользователь с таким именем уже существует', 'danger')
|
||||||
conn.close()
|
conn.close()
|
||||||
return redirect(url_for('register'))
|
return redirect(url_for('register'))
|
||||||
|
|
||||||
hashed_password = generate_password_hash(password)
|
hashed_password = generate_password_hash(password)
|
||||||
conn.execute('INSERT INTO users (username, password, email, role) VALUES (?, ?, ?, ?)',
|
conn.execute('INSERT INTO users (username, password, email, role) VALUES (?, ?, ?, ?)',
|
||||||
(username, hashed_password, email if email else None, 'user'))
|
(username, hashed_password, email if email else None, 'user'))
|
||||||
|
|
@ -247,17 +283,20 @@ def order():
|
||||||
persons = request.form.get('persons', 1)
|
persons = request.form.get('persons', 1)
|
||||||
price = request.form.get('price', 0)
|
price = request.form.get('price', 0)
|
||||||
comment = request.form.get('comment', '')
|
comment = request.form.get('comment', '')
|
||||||
|
|
||||||
try:
|
try:
|
||||||
persons = int(float(persons)) if service_type != 'certificate' else 1
|
persons = int(float(persons)) if service_type != 'certificate' else 1
|
||||||
if persons < 1: persons = 1
|
if persons < 1: persons = 1
|
||||||
if persons > 20: persons = 20
|
if persons > 20: persons = 20
|
||||||
except:
|
except:
|
||||||
persons = 1
|
persons = 1
|
||||||
|
|
||||||
conn = get_db_connection()
|
conn = get_db_connection()
|
||||||
final_price = int(price)
|
final_price = int(price)
|
||||||
discount_applied = False
|
discount_applied = False
|
||||||
discount_amount = 0
|
discount_amount = 0
|
||||||
original_price = int(price)
|
original_price = int(price)
|
||||||
|
|
||||||
if service_type != 'certificate':
|
if service_type != 'certificate':
|
||||||
duration_minutes = 0
|
duration_minutes = 0
|
||||||
duration_str = ''
|
duration_str = ''
|
||||||
|
|
@ -270,15 +309,18 @@ def order():
|
||||||
elif 'час' in duration_str:
|
elif 'час' in duration_str:
|
||||||
hours = int(duration_str.split()[0])
|
hours = int(duration_str.split()[0])
|
||||||
duration_minutes = hours * 60
|
duration_minutes = hours * 60
|
||||||
|
|
||||||
try:
|
try:
|
||||||
hour = int(time.split(':')[0])
|
hour = int(time.split(':')[0])
|
||||||
minute = int(time.split(':')[1])
|
minute = int(time.split(':')[1])
|
||||||
start_minutes = hour * 60 + minute
|
start_minutes = hour * 60 + minute
|
||||||
end_minutes = start_minutes + duration_minutes
|
end_minutes = start_minutes + duration_minutes
|
||||||
|
|
||||||
if start_minutes < 540:
|
if start_minutes < 540:
|
||||||
flash('Заказы принимаются с 9:00', 'danger')
|
flash('Заказы принимаются с 9:00', 'danger')
|
||||||
conn.close()
|
conn.close()
|
||||||
return redirect(url_for('order'))
|
return redirect(url_for('order'))
|
||||||
|
|
||||||
if end_minutes > 1200:
|
if end_minutes > 1200:
|
||||||
max_hour = (1200 - duration_minutes) // 60
|
max_hour = (1200 - duration_minutes) // 60
|
||||||
max_minute = (1200 - duration_minutes) % 60
|
max_minute = (1200 - duration_minutes) % 60
|
||||||
|
|
@ -289,15 +331,18 @@ def order():
|
||||||
flash('Неверный формат времени', 'danger')
|
flash('Неверный формат времени', 'danger')
|
||||||
conn.close()
|
conn.close()
|
||||||
return redirect(url_for('order'))
|
return redirect(url_for('order'))
|
||||||
|
|
||||||
today = datetime.now().strftime('%Y-%m-%d')
|
today = datetime.now().strftime('%Y-%m-%d')
|
||||||
if date < today:
|
if date < today:
|
||||||
flash('Нельзя выбрать прошедшую дату', 'danger')
|
flash('Нельзя выбрать прошедшую дату', 'danger')
|
||||||
conn.close()
|
conn.close()
|
||||||
return redirect(url_for('order'))
|
return redirect(url_for('order'))
|
||||||
|
|
||||||
if persons >= 4 and service_type == 'service':
|
if persons >= 4 and service_type == 'service':
|
||||||
discount_amount = int(int(price) * 0.15)
|
discount_amount = int(int(price) * 0.15)
|
||||||
final_price = int(int(price) * 0.85)
|
final_price = int(int(price) * 0.85)
|
||||||
discount_applied = True
|
discount_applied = True
|
||||||
|
|
||||||
conn.execute('''
|
conn.execute('''
|
||||||
INSERT INTO orders
|
INSERT INTO orders
|
||||||
(user_id, service_type, service_name, service_id, date, time, persons, price, comment, discount_applied, discount_amount, original_price, payment_status)
|
(user_id, service_type, service_name, service_id, date, time, persons, price, comment, discount_applied, discount_amount, original_price, payment_status)
|
||||||
|
|
@ -305,11 +350,13 @@ def order():
|
||||||
''', (session['user_id'], service_type, service_name, service_id, date, time, persons, final_price, comment, discount_applied, discount_amount, original_price))
|
''', (session['user_id'], service_type, service_name, service_id, date, time, persons, final_price, comment, discount_applied, discount_amount, original_price))
|
||||||
conn.commit()
|
conn.commit()
|
||||||
conn.close()
|
conn.close()
|
||||||
|
|
||||||
if discount_applied:
|
if discount_applied:
|
||||||
flash(f'Заказ успешно создан! Применена семейная скидка 15%! Итоговая цена: {final_price} руб.', 'success')
|
flash(f'Заказ успешно создан! Применена семейная скидка 15%! Итоговая цена: {final_price} руб.', 'success')
|
||||||
else:
|
else:
|
||||||
flash('Заказ успешно создан!', 'success')
|
flash('Заказ успешно создан!', 'success')
|
||||||
return redirect(url_for('my_orders'))
|
return redirect(url_for('my_orders'))
|
||||||
|
|
||||||
return render_template('order_form.html')
|
return render_template('order_form.html')
|
||||||
|
|
||||||
@app.route('/my-orders')
|
@app.route('/my-orders')
|
||||||
|
|
@ -318,6 +365,7 @@ def my_orders():
|
||||||
sort = request.args.get('sort', 'newest')
|
sort = request.args.get('sort', 'newest')
|
||||||
status = request.args.get('status', 'all')
|
status = request.args.get('status', 'all')
|
||||||
conn = get_db_connection()
|
conn = get_db_connection()
|
||||||
|
|
||||||
query = 'SELECT * FROM orders WHERE user_id = ?'
|
query = 'SELECT * FROM orders WHERE user_id = ?'
|
||||||
params = [session['user_id']]
|
params = [session['user_id']]
|
||||||
if status != 'all':
|
if status != 'all':
|
||||||
|
|
@ -331,6 +379,7 @@ def my_orders():
|
||||||
query += ' ORDER BY price DESC'
|
query += ' ORDER BY price DESC'
|
||||||
elif sort == 'price_low':
|
elif sort == 'price_low':
|
||||||
query += ' ORDER BY price ASC'
|
query += ' ORDER BY price ASC'
|
||||||
|
|
||||||
orders = conn.execute(query, params).fetchall()
|
orders = conn.execute(query, params).fetchall()
|
||||||
orders_list = []
|
orders_list = []
|
||||||
for order in orders:
|
for order in orders:
|
||||||
|
|
@ -341,6 +390,7 @@ def my_orders():
|
||||||
''', (order['id'],)).fetchone()
|
''', (order['id'],)).fetchone()
|
||||||
order_dict['unread_count'] = unread['count'] if unread else 0
|
order_dict['unread_count'] = unread['count'] if unread else 0
|
||||||
orders_list.append(order_dict)
|
orders_list.append(order_dict)
|
||||||
|
|
||||||
conn.close()
|
conn.close()
|
||||||
return render_template('my_orders.html', orders=orders_list, sort=sort, status=status)
|
return render_template('my_orders.html', orders=orders_list, sort=sort, status=status)
|
||||||
|
|
||||||
|
|
@ -351,9 +401,11 @@ def reviews():
|
||||||
if 'user_id' not in session:
|
if 'user_id' not in session:
|
||||||
flash('Пожалуйста, войдите в систему, чтобы оставить отзыв', 'warning')
|
flash('Пожалуйста, войдите в систему, чтобы оставить отзыв', 'warning')
|
||||||
return redirect(url_for('login'))
|
return redirect(url_for('login'))
|
||||||
|
|
||||||
order_id = request.form.get('order_id')
|
order_id = request.form.get('order_id')
|
||||||
rating = int(request.form['rating'])
|
rating = int(request.form['rating'])
|
||||||
comment = request.form['comment']
|
comment = request.form['comment']
|
||||||
|
|
||||||
conn = get_db_connection()
|
conn = get_db_connection()
|
||||||
existing_review = conn.execute('SELECT * FROM reviews WHERE user_id = ? AND order_id = ?',
|
existing_review = conn.execute('SELECT * FROM reviews WHERE user_id = ? AND order_id = ?',
|
||||||
(session['user_id'], order_id)).fetchone()
|
(session['user_id'], order_id)).fetchone()
|
||||||
|
|
@ -361,12 +413,14 @@ def reviews():
|
||||||
flash('Вы уже оставляли отзыв на этот заказ', 'danger')
|
flash('Вы уже оставляли отзыв на этот заказ', 'danger')
|
||||||
conn.close()
|
conn.close()
|
||||||
return redirect(url_for('reviews'))
|
return redirect(url_for('reviews'))
|
||||||
|
|
||||||
order = conn.execute('SELECT * FROM orders WHERE id = ? AND user_id = ? AND status = "completed"',
|
order = conn.execute('SELECT * FROM orders WHERE id = ? AND user_id = ? AND status = "completed"',
|
||||||
(order_id, session['user_id'])).fetchone()
|
(order_id, session['user_id'])).fetchone()
|
||||||
if not order:
|
if not order:
|
||||||
flash('Вы можете оставить отзыв только на выполненные заказы', 'danger')
|
flash('Вы можете оставить отзыв только на выполненные заказы', 'danger')
|
||||||
conn.close()
|
conn.close()
|
||||||
return redirect(url_for('reviews'))
|
return redirect(url_for('reviews'))
|
||||||
|
|
||||||
conn.execute('''
|
conn.execute('''
|
||||||
INSERT INTO reviews (user_id, order_id, username, rating, comment, status)
|
INSERT INTO reviews (user_id, order_id, username, rating, comment, status)
|
||||||
VALUES (?, ?, ?, ?, ?, 'pending')
|
VALUES (?, ?, ?, ?, ?, 'pending')
|
||||||
|
|
@ -375,9 +429,11 @@ def reviews():
|
||||||
conn.close()
|
conn.close()
|
||||||
flash('Ваш отзыв отправлен на модерацию!', 'success')
|
flash('Ваш отзыв отправлен на модерацию!', 'success')
|
||||||
return redirect(url_for('reviews'))
|
return redirect(url_for('reviews'))
|
||||||
|
|
||||||
sort = request.args.get('sort', 'newest')
|
sort = request.args.get('sort', 'newest')
|
||||||
rating_filter = request.args.get('rating', 'all')
|
rating_filter = request.args.get('rating', 'all')
|
||||||
conn = get_db_connection()
|
conn = get_db_connection()
|
||||||
|
|
||||||
completed_orders = []
|
completed_orders = []
|
||||||
if 'user_id' in session:
|
if 'user_id' in session:
|
||||||
completed_orders = conn.execute('''
|
completed_orders = conn.execute('''
|
||||||
|
|
@ -386,6 +442,7 @@ def reviews():
|
||||||
WHERE o.user_id = ? AND o.status = 'completed' AND r.id IS NULL
|
WHERE o.user_id = ? AND o.status = 'completed' AND r.id IS NULL
|
||||||
ORDER BY o.created_at DESC
|
ORDER BY o.created_at DESC
|
||||||
''', (session['user_id'], session['user_id'])).fetchall()
|
''', (session['user_id'], session['user_id'])).fetchall()
|
||||||
|
|
||||||
query = 'SELECT * FROM reviews WHERE status = "approved"'
|
query = 'SELECT * FROM reviews WHERE status = "approved"'
|
||||||
params = []
|
params = []
|
||||||
if rating_filter != 'all':
|
if rating_filter != 'all':
|
||||||
|
|
@ -399,6 +456,7 @@ def reviews():
|
||||||
query += ' ORDER BY rating DESC'
|
query += ' ORDER BY rating DESC'
|
||||||
elif sort == 'rating_low':
|
elif sort == 'rating_low':
|
||||||
query += ' ORDER BY rating ASC'
|
query += ' ORDER BY rating ASC'
|
||||||
|
|
||||||
approved_reviews = conn.execute(query, params).fetchall()
|
approved_reviews = conn.execute(query, params).fetchall()
|
||||||
conn.close()
|
conn.close()
|
||||||
return render_template('reviews.html', reviews=approved_reviews,
|
return render_template('reviews.html', reviews=approved_reviews,
|
||||||
|
|
@ -417,8 +475,10 @@ def chat(order_id):
|
||||||
if session['user_id'] != order['user_id'] and session.get('role') != 'admin':
|
if session['user_id'] != order['user_id'] and session.get('role') != 'admin':
|
||||||
flash('Доступ запрещен', 'danger')
|
flash('Доступ запрещен', 'danger')
|
||||||
return redirect(url_for('index'))
|
return redirect(url_for('index'))
|
||||||
|
|
||||||
if session.get('role') == 'admin':
|
if session.get('role') == 'admin':
|
||||||
conn.execute('UPDATE messages SET is_read = 1 WHERE order_id = ? AND sender_type = "user"', (order_id,))
|
conn.execute('UPDATE messages SET is_read = 1 WHERE order_id = ? AND sender_type = "user"', (order_id,))
|
||||||
|
|
||||||
messages = conn.execute('''
|
messages = conn.execute('''
|
||||||
SELECT m.*,
|
SELECT m.*,
|
||||||
CASE
|
CASE
|
||||||
|
|
@ -442,6 +502,7 @@ def send_message():
|
||||||
message = request.form['message']
|
message = request.form['message']
|
||||||
if not message or not message.strip():
|
if not message or not message.strip():
|
||||||
return jsonify({'error': 'Сообщение не может быть пустым'}), 400
|
return jsonify({'error': 'Сообщение не может быть пустым'}), 400
|
||||||
|
|
||||||
conn = get_db_connection()
|
conn = get_db_connection()
|
||||||
order = conn.execute('SELECT * FROM orders WHERE id = ?', (order_id,)).fetchone()
|
order = conn.execute('SELECT * FROM orders WHERE id = ?', (order_id,)).fetchone()
|
||||||
if not order:
|
if not order:
|
||||||
|
|
@ -450,6 +511,7 @@ def send_message():
|
||||||
if session['user_id'] != order['user_id'] and session.get('role') != 'admin':
|
if session['user_id'] != order['user_id'] and session.get('role') != 'admin':
|
||||||
conn.close()
|
conn.close()
|
||||||
return jsonify({'error': 'Доступ запрещен'}), 403
|
return jsonify({'error': 'Доступ запрещен'}), 403
|
||||||
|
|
||||||
if session.get('role') == 'admin':
|
if session.get('role') == 'admin':
|
||||||
sender_type = 'admin'
|
sender_type = 'admin'
|
||||||
admin_id = session['user_id']
|
admin_id = session['user_id']
|
||||||
|
|
@ -458,6 +520,7 @@ def send_message():
|
||||||
sender_type = 'user'
|
sender_type = 'user'
|
||||||
user_id = session['user_id']
|
user_id = session['user_id']
|
||||||
admin_id = None
|
admin_id = None
|
||||||
|
|
||||||
conn.execute('''
|
conn.execute('''
|
||||||
INSERT INTO messages (order_id, user_id, admin_id, message, sender_type)
|
INSERT INTO messages (order_id, user_id, admin_id, message, sender_type)
|
||||||
VALUES (?, ?, ?, ?, ?)
|
VALUES (?, ?, ?, ?, ?)
|
||||||
|
|
@ -497,6 +560,7 @@ def admin_orders():
|
||||||
query += ' ORDER BY o.price DESC'
|
query += ' ORDER BY o.price DESC'
|
||||||
elif sort == 'price_low':
|
elif sort == 'price_low':
|
||||||
query += ' ORDER BY o.price ASC'
|
query += ' ORDER BY o.price ASC'
|
||||||
|
|
||||||
orders = conn.execute(query, params).fetchall()
|
orders = conn.execute(query, params).fetchall()
|
||||||
conn.close()
|
conn.close()
|
||||||
return render_template('admin/orders.html', orders=orders, sort=sort, status=status)
|
return render_template('admin/orders.html', orders=orders, sort=sort, status=status)
|
||||||
|
|
@ -556,6 +620,7 @@ def admin_reviews():
|
||||||
query += ' ORDER BY rating DESC'
|
query += ' ORDER BY rating DESC'
|
||||||
elif sort == 'rating_low':
|
elif sort == 'rating_low':
|
||||||
query += ' ORDER BY rating ASC'
|
query += ' ORDER BY rating ASC'
|
||||||
|
|
||||||
reviews = conn.execute(query, params).fetchall()
|
reviews = conn.execute(query, params).fetchall()
|
||||||
conn.close()
|
conn.close()
|
||||||
return render_template('admin/reviews.html', reviews=reviews, sort=sort, status=status, rating=rating)
|
return render_template('admin/reviews.html', reviews=reviews, sort=sort, status=status, rating=rating)
|
||||||
|
|
@ -606,6 +671,7 @@ def admin_users():
|
||||||
query += ' ORDER BY username ASC'
|
query += ' ORDER BY username ASC'
|
||||||
elif sort == 'name_desc':
|
elif sort == 'name_desc':
|
||||||
query += ' ORDER BY username DESC'
|
query += ' ORDER BY username DESC'
|
||||||
|
|
||||||
users = conn.execute(query, params).fetchall()
|
users = conn.execute(query, params).fetchall()
|
||||||
conn.close()
|
conn.close()
|
||||||
return render_template('admin/users.html', users=users, sort=sort, role=role)
|
return render_template('admin/users.html', users=users, sort=sort, role=role)
|
||||||
|
|
@ -659,18 +725,25 @@ def admin_messages():
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
conn = sqlite3.connect('horse_farm.db')
|
conn = sqlite3.connect('horse_farm.db')
|
||||||
cursor = conn.cursor()
|
cursor = conn.cursor()
|
||||||
|
|
||||||
cursor.execute("PRAGMA table_info(orders)")
|
cursor.execute("PRAGMA table_info(orders)")
|
||||||
existing = [col[1] for col in cursor.fetchall()]
|
existing = [col[1] for col in cursor.fetchall()]
|
||||||
for col in ['discount_applied', 'discount_amount', 'original_price', 'payment_status']:
|
for col in ['discount_applied', 'discount_amount', 'original_price', 'payment_status']:
|
||||||
if col not in existing:
|
if col not in existing:
|
||||||
cursor.execute(f"ALTER TABLE orders ADD COLUMN {col} DEFAULT 'not_paid' if col == 'payment_status' else 0")
|
if col == 'payment_status':
|
||||||
|
cursor.execute(f"ALTER TABLE orders ADD COLUMN {col} TEXT DEFAULT 'not_paid'")
|
||||||
|
else:
|
||||||
|
cursor.execute(f"ALTER TABLE orders ADD COLUMN {col} INTEGER DEFAULT 0")
|
||||||
print(f"Добавлена колонка {col}")
|
print(f"Добавлена колонка {col}")
|
||||||
|
|
||||||
cursor.execute("PRAGMA table_info(reviews)")
|
cursor.execute("PRAGMA table_info(reviews)")
|
||||||
if 'order_id' not in [c[1] for c in cursor.fetchall()]:
|
if 'order_id' not in [c[1] for c in cursor.fetchall()]:
|
||||||
cursor.execute("ALTER TABLE reviews ADD COLUMN order_id INTEGER")
|
cursor.execute("ALTER TABLE reviews ADD COLUMN order_id INTEGER")
|
||||||
|
|
||||||
cursor.execute("PRAGMA table_info(messages)")
|
cursor.execute("PRAGMA table_info(messages)")
|
||||||
if 'is_read' not in [c[1] for c in cursor.fetchall()]:
|
if 'is_read' not in [c[1] for c in cursor.fetchall()]:
|
||||||
cursor.execute("ALTER TABLE messages ADD COLUMN is_read BOOLEAN DEFAULT 0")
|
cursor.execute("ALTER TABLE messages ADD COLUMN is_read BOOLEAN DEFAULT 0")
|
||||||
|
|
||||||
cursor.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='messages'")
|
cursor.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='messages'")
|
||||||
if not cursor.fetchone():
|
if not cursor.fetchone():
|
||||||
cursor.execute('''
|
cursor.execute('''
|
||||||
|
|
@ -685,12 +758,14 @@ if __name__ == '__main__':
|
||||||
is_read BOOLEAN DEFAULT 0
|
is_read BOOLEAN DEFAULT 0
|
||||||
)
|
)
|
||||||
''')
|
''')
|
||||||
|
|
||||||
cursor.execute("SELECT * FROM users WHERE username = 'admin'")
|
cursor.execute("SELECT * FROM users WHERE username = 'admin'")
|
||||||
if not cursor.fetchone():
|
if not cursor.fetchone():
|
||||||
hashed = generate_password_hash('admin123')
|
hashed = generate_password_hash('admin123')
|
||||||
cursor.execute("INSERT INTO users (username, password, email, role) VALUES (?, ?, ?, ?)",
|
cursor.execute("INSERT INTO users (username, password, email, role) VALUES (?, ?, ?, ?)",
|
||||||
('admin', hashed, 'admin@koniydvor.ru', 'admin'))
|
('admin', hashed, 'admin@koniydvor.ru', 'admin'))
|
||||||
print("Создан администратор: admin / admin123")
|
print("Создан администратор: admin / admin123")
|
||||||
|
|
||||||
conn.commit()
|
conn.commit()
|
||||||
conn.close()
|
conn.close()
|
||||||
app.run(debug=True)
|
app.run(debug=True)
|
||||||
|
|
|
||||||
BIN
horse_farm.db
BIN
horse_farm.db
Binary file not shown.
|
|
@ -10,24 +10,20 @@
|
||||||
border-radius: 20px;
|
border-radius: 20px;
|
||||||
border: 1px solid rgba(255, 255, 255, 0.2);
|
border: 1px solid rgba(255, 255, 255, 0.2);
|
||||||
}
|
}
|
||||||
|
|
||||||
.auth-container h2 {
|
.auth-container h2 {
|
||||||
color: #f5cba0;
|
color: #f5cba0;
|
||||||
margin-bottom: 1.5rem;
|
margin-bottom: 1.5rem;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.form-group {
|
.form-group {
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.form-group label {
|
.form-group label {
|
||||||
display: block;
|
display: block;
|
||||||
margin-bottom: 0.3rem;
|
margin-bottom: 0.3rem;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
color: #f5cba0;
|
color: #f5cba0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.form-group input {
|
.form-group input {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: 0.6rem;
|
padding: 0.6rem;
|
||||||
|
|
@ -37,15 +33,13 @@
|
||||||
background: rgba(255, 255, 255, 0.9);
|
background: rgba(255, 255, 255, 0.9);
|
||||||
color: #2c2c2c;
|
color: #2c2c2c;
|
||||||
}
|
}
|
||||||
|
|
||||||
.form-group input:focus {
|
.form-group input:focus {
|
||||||
outline: none;
|
outline: none;
|
||||||
border-color: #f5cba0;
|
border-color: #f5cba0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-primary {
|
.btn-primary {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
background: linear-gradient(135deg, #f5cba0 0%, #d4a373 100%);
|
background: #f5cba0;
|
||||||
color: #2c1810;
|
color: #2c1810;
|
||||||
padding: 0.75rem;
|
padding: 0.75rem;
|
||||||
border: none;
|
border: none;
|
||||||
|
|
@ -53,34 +47,29 @@
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: all 0.2s ease;
|
transition: 0.2s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-primary:hover {
|
.btn-primary:hover {
|
||||||
background: linear-gradient(135deg, #ffdd99 0%, #f5cba0 100%);
|
background: #ffdd99;
|
||||||
transform: translateY(-2px);
|
transform: translateY(-2px);
|
||||||
}
|
}
|
||||||
|
|
||||||
.auth-link {
|
.auth-link {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
margin-top: 1rem;
|
margin-top: 1rem;
|
||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
.auth-link a {
|
.auth-link a {
|
||||||
color: #f5cba0;
|
color: #f5cba0;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.auth-link a:hover {
|
.auth-link a:hover {
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
|
|
||||||
small {
|
small {
|
||||||
display: block;
|
display: block;
|
||||||
margin-top: 0.25rem;
|
margin-top: 0.25rem;
|
||||||
font-size: 0.7rem;
|
font-size: 0.7rem;
|
||||||
color: #f5cba0;
|
color: #ffffff !important;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|
@ -98,18 +87,18 @@
|
||||||
<form method="POST" class="auth-form">
|
<form method="POST" class="auth-form">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="username">Имя пользователя:</label>
|
<label for="username">Имя пользователя:</label>
|
||||||
<input type="text" id="username" name="username" required>
|
<input type="text" id="username" name="username" required maxlength="50">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="email">Email (необязательно):</label>
|
<label for="email">Email (необязательно):</label>
|
||||||
<input type="email" id="email" name="email" placeholder="example@mail.ru">
|
<input type="email" id="email" name="email" placeholder="example@mail.ru" maxlength="50">
|
||||||
<small>Формат: name@domain.ru</small>
|
<small>Максимум 50 символов, локальная часть (до @) - до 20 символов</small>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="password">Пароль:</label>
|
<label for="password">Пароль:</label>
|
||||||
<input type="password" id="password" name="password" required>
|
<input type="password" id="password" name="password" required minlength="4" maxlength="100">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button type="submit" class="btn-primary">Зарегистрироваться</button>
|
<button type="submit" class="btn-primary">Зарегистрироваться</button>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue