flask-core-utils 2.0.0__tar.gz → 2.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {flask_core_utils-2.0.0 → flask_core_utils-2.2.0}/PKG-INFO +1 -1
- {flask_core_utils-2.0.0 → flask_core_utils-2.2.0}/flask_core_utils/__init__.py +33 -37
- {flask_core_utils-2.0.0 → flask_core_utils-2.2.0}/flask_core_utils.egg-info/PKG-INFO +1 -1
- {flask_core_utils-2.0.0 → flask_core_utils-2.2.0}/setup.py +1 -1
- {flask_core_utils-2.0.0 → flask_core_utils-2.2.0}/README.md +0 -0
- {flask_core_utils-2.0.0 → flask_core_utils-2.2.0}/flask_core_utils.egg-info/SOURCES.txt +0 -0
- {flask_core_utils-2.0.0 → flask_core_utils-2.2.0}/flask_core_utils.egg-info/dependency_links.txt +0 -0
- {flask_core_utils-2.0.0 → flask_core_utils-2.2.0}/flask_core_utils.egg-info/top_level.txt +0 -0
- {flask_core_utils-2.0.0 → flask_core_utils-2.2.0}/setup.cfg +0 -0
|
@@ -158,29 +158,29 @@ reportlabh
|
|
|
158
158
|
'''
|
|
159
159
|
|
|
160
160
|
BASH_CONTENT = r'''#!/bin/bash
|
|
161
|
-
#
|
|
161
|
+
# Быстрый запуск сервера и генератора
|
|
162
162
|
chmod +x start.sh
|
|
163
163
|
python3 check.py
|
|
164
164
|
python3 app.py
|
|
165
165
|
'''
|
|
166
166
|
|
|
167
|
-
README_CONTENT = r'''#
|
|
167
|
+
README_CONTENT = r'''# Веб-приложение
|
|
168
168
|
|
|
169
|
-
|
|
169
|
+
Система для оформления заявок и генерации чеков.
|
|
170
170
|
|
|
171
|
-
##
|
|
172
|
-
* app.py
|
|
173
|
-
* check.py
|
|
174
|
-
* script.sql
|
|
175
|
-
* start.sh
|
|
171
|
+
## Файлы
|
|
172
|
+
* app.py — сервер (Flask)
|
|
173
|
+
* check.py — генерация PDF-чека
|
|
174
|
+
* script.sql — структура таблиц
|
|
175
|
+
* start.sh — быстрый запуск (чек+приложение)
|
|
176
176
|
|
|
177
|
-
##
|
|
178
|
-
1.
|
|
179
|
-
2.
|
|
177
|
+
## Запуск
|
|
178
|
+
1. Дать права скрипту (если потребуется): `chmod +x start.sh`
|
|
179
|
+
2. Запустить проект: `./start.sh` или `python3 app.py`
|
|
180
180
|
'''
|
|
181
181
|
|
|
182
182
|
SQL_CONTENT = r'''
|
|
183
|
-
-- Справочники
|
|
183
|
+
-- Справочники
|
|
184
184
|
CREATE TABLE roles (
|
|
185
185
|
id SERIAL PRIMARY KEY,
|
|
186
186
|
name VARCHAR(50) UNIQUE NOT NULL
|
|
@@ -201,7 +201,7 @@ CREATE TABLE courses (
|
|
|
201
201
|
title VARCHAR(150) UNIQUE NOT NULL
|
|
202
202
|
);
|
|
203
203
|
|
|
204
|
-
-- Основные таблицы
|
|
204
|
+
-- Основные таблицы
|
|
205
205
|
CREATE TABLE users (
|
|
206
206
|
id SERIAL PRIMARY KEY,
|
|
207
207
|
login VARCHAR(50) UNIQUE NOT NULL,
|
|
@@ -228,7 +228,7 @@ CREATE TABLE reviews (
|
|
|
228
228
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
229
229
|
);
|
|
230
230
|
|
|
231
|
-
-- Заполнение
|
|
231
|
+
-- Заполнение базовыми данными
|
|
232
232
|
INSERT INTO roles (name) VALUES ('user'), ('admin');
|
|
233
233
|
|
|
234
234
|
INSERT INTO statuses (name) VALUES
|
|
@@ -245,7 +245,7 @@ INSERT INTO courses (title) VALUES
|
|
|
245
245
|
('Основы веб-дизайна'),
|
|
246
246
|
('Основы проектирования баз данных');
|
|
247
247
|
|
|
248
|
-
--
|
|
248
|
+
-- Учетка админа
|
|
249
249
|
INSERT INTO users (login, password, fio, phone, email, role_id)
|
|
250
250
|
VALUES ('Admin', 'KorokNET', 'Администратор', '8(999) 999-99-99', 'admin@system.local', 2);
|
|
251
251
|
'''
|
|
@@ -257,18 +257,16 @@ from psycopg2.extras import DictCursor
|
|
|
257
257
|
from werkzeug.security import generate_password_hash, check_password_hash
|
|
258
258
|
import re
|
|
259
259
|
|
|
260
|
-
# Initialize the main Flask application
|
|
261
260
|
app = Flask(__name__)
|
|
262
261
|
app.secret_key = 'dev_key_123'
|
|
263
262
|
|
|
263
|
+
# Класс для работы с БД
|
|
264
264
|
class Database:
|
|
265
|
-
"""Wrapper class for database connection and query execution."""
|
|
266
265
|
def __init__(self):
|
|
267
|
-
# Database connection configuration
|
|
268
266
|
self.conn_str = "dbname='exam_db' user='postgres' password='' host='127.0.0.1'"
|
|
269
267
|
|
|
268
|
+
# Метод для выполнения запросов
|
|
270
269
|
def query(self, sql, params=(), fetchone=False, fetchall=False):
|
|
271
|
-
"""Executes a SQL query and returns fetched data if requested."""
|
|
272
270
|
with psycopg2.connect(self.conn_str) as conn:
|
|
273
271
|
with conn.cursor(cursor_factory=DictCursor) as cur:
|
|
274
272
|
cur.execute(sql, params)
|
|
@@ -278,9 +276,9 @@ class Database:
|
|
|
278
276
|
|
|
279
277
|
db = Database()
|
|
280
278
|
|
|
279
|
+
# Главная страница
|
|
281
280
|
@app.route('/')
|
|
282
281
|
def index():
|
|
283
|
-
"""Renders the main landing page with recent reviews."""
|
|
284
282
|
reviews = db.query("""
|
|
285
283
|
SELECT rv.review_text, u.fio, c.title as course
|
|
286
284
|
FROM reviews rv
|
|
@@ -291,18 +289,18 @@ def index():
|
|
|
291
289
|
""", fetchall=True)
|
|
292
290
|
return render_template('index.html', reviews=reviews)
|
|
293
291
|
|
|
292
|
+
# Регистрация
|
|
294
293
|
@app.route('/register', methods=['GET', 'POST'])
|
|
295
294
|
def register():
|
|
296
|
-
"""Handles new user registration and input validation."""
|
|
297
295
|
if request.method == 'POST':
|
|
298
|
-
#
|
|
296
|
+
# Получаем данные из формы
|
|
299
297
|
login = request.form.get('login', '').strip()
|
|
300
298
|
password = request.form.get('password', '')
|
|
301
299
|
fio = request.form.get('fio', '').strip()
|
|
302
300
|
phone = request.form.get('phone', '').strip()
|
|
303
301
|
email = request.form.get('email', '').strip()
|
|
304
302
|
|
|
305
|
-
#
|
|
303
|
+
# Валидация
|
|
306
304
|
if not re.match(r'^[A-Za-z0-9]{6,}$', login):
|
|
307
305
|
flash("Логин должен состоять из латиницы и цифр (не менее 6 символов)", "error")
|
|
308
306
|
return redirect('/register')
|
|
@@ -311,7 +309,7 @@ def register():
|
|
|
311
309
|
return redirect('/register')
|
|
312
310
|
|
|
313
311
|
try:
|
|
314
|
-
#
|
|
312
|
+
# Хэшируем пароль
|
|
315
313
|
hashed_password = generate_password_hash(password)
|
|
316
314
|
db.query("""
|
|
317
315
|
INSERT INTO users (login, password, fio, phone, email, role_id)
|
|
@@ -324,25 +322,24 @@ def register():
|
|
|
324
322
|
|
|
325
323
|
return render_template('register.html')
|
|
326
324
|
|
|
325
|
+
# Авторизация
|
|
327
326
|
@app.route('/login', methods=['GET', 'POST'])
|
|
328
327
|
def login():
|
|
329
|
-
"""Handles user authentication and session management."""
|
|
330
328
|
if request.method == 'POST':
|
|
331
329
|
login_input = request.form.get('login')
|
|
332
330
|
password_input = request.form.get('password')
|
|
333
331
|
|
|
334
|
-
# Retrieve user record by login
|
|
335
332
|
user = db.query("SELECT * FROM users WHERE login=%s", (login_input,), fetchone=True)
|
|
336
333
|
|
|
337
334
|
if user:
|
|
338
335
|
is_valid = False
|
|
339
|
-
#
|
|
336
|
+
# Проверка пароля (для админа без хэша)
|
|
340
337
|
if user['login'] == 'Admin' and user['password'] == password_input:
|
|
341
338
|
is_valid = True
|
|
342
339
|
elif user['login'] != 'Admin' and check_password_hash(user['password'], password_input):
|
|
343
340
|
is_valid = True
|
|
344
341
|
|
|
345
|
-
#
|
|
342
|
+
# Записываем в сессию
|
|
346
343
|
if is_valid:
|
|
347
344
|
session['user_id'] = user['id']
|
|
348
345
|
session['role_id'] = user['role_id']
|
|
@@ -352,13 +349,14 @@ def login():
|
|
|
352
349
|
flash("Неверный логин или пароль", "error")
|
|
353
350
|
return render_template('login.html')
|
|
354
351
|
|
|
352
|
+
# Личный кабинет
|
|
355
353
|
@app.route('/account', methods=['GET', 'POST'])
|
|
356
354
|
def account():
|
|
357
|
-
|
|
355
|
+
# Проверка доступа
|
|
358
356
|
if 'user_id' not in session or session.get('role_id') != 1:
|
|
359
357
|
return redirect('/login')
|
|
360
358
|
|
|
361
|
-
#
|
|
359
|
+
# Добавление новой заявки
|
|
362
360
|
if request.method == 'POST':
|
|
363
361
|
db.query("""
|
|
364
362
|
INSERT INTO requests (user_id, course_id, start_date, payment_method_id, status_id)
|
|
@@ -368,10 +366,10 @@ def account():
|
|
|
368
366
|
flash("Заявка успешно отправлена", "success")
|
|
369
367
|
return redirect('/account')
|
|
370
368
|
|
|
371
|
-
# Fetch reference data and user history
|
|
372
369
|
courses = db.query("SELECT * FROM courses", fetchall=True)
|
|
373
370
|
payments = db.query("SELECT * FROM payment_methods", fetchall=True)
|
|
374
371
|
|
|
372
|
+
# История заявок пользователя
|
|
375
373
|
user_requests = db.query("""
|
|
376
374
|
SELECT r.id, c.title as course, r.start_date, s.name as status, s.id as status_id, rv.review_text
|
|
377
375
|
FROM requests r
|
|
@@ -383,27 +381,26 @@ def account():
|
|
|
383
381
|
|
|
384
382
|
return render_template('account.html', courses=courses, payments=payments, requests=user_requests)
|
|
385
383
|
|
|
384
|
+
# Оставить отзыв
|
|
386
385
|
@app.route('/leave_review', methods=['POST'])
|
|
387
386
|
def leave_review():
|
|
388
|
-
"""Endpoint for users to submit a review."""
|
|
389
387
|
if 'user_id' in session:
|
|
390
388
|
db.query("INSERT INTO reviews (request_id, review_text) VALUES (%s, %s)",
|
|
391
389
|
(request.form.get('req_id'), request.form.get('review_text')))
|
|
392
390
|
return redirect('/account')
|
|
393
391
|
|
|
392
|
+
# Панель администратора
|
|
394
393
|
@app.route('/admin', methods=['GET', 'POST'])
|
|
395
394
|
def admin():
|
|
396
|
-
"""Administrative panel for managing user requests."""
|
|
397
395
|
if session.get('role_id') != 2:
|
|
398
396
|
return redirect('/login')
|
|
399
397
|
|
|
400
|
-
#
|
|
398
|
+
# Смена статуса
|
|
401
399
|
if request.method == 'POST':
|
|
402
400
|
db.query("UPDATE requests SET status_id=%s WHERE id=%s",
|
|
403
401
|
(request.form.get('status_id'), request.form.get('req_id')))
|
|
404
402
|
return redirect('/admin')
|
|
405
403
|
|
|
406
|
-
# Fetch all system requests and statuses
|
|
407
404
|
statuses = db.query("SELECT * FROM statuses", fetchall=True)
|
|
408
405
|
all_requests = db.query("""
|
|
409
406
|
SELECT r.id, u.fio, u.phone, c.title as course, r.start_date, pm.name as payment, s.id as status_id, s.name as status
|
|
@@ -417,14 +414,13 @@ def admin():
|
|
|
417
414
|
|
|
418
415
|
return render_template('admin.html', requests=all_requests, statuses=statuses)
|
|
419
416
|
|
|
417
|
+
# Выход
|
|
420
418
|
@app.route('/logout')
|
|
421
419
|
def logout():
|
|
422
|
-
"""Clears the session and logs the user out."""
|
|
423
420
|
session.clear()
|
|
424
421
|
return redirect('/')
|
|
425
422
|
|
|
426
423
|
if __name__ == '__main__':
|
|
427
|
-
# Start the server
|
|
428
424
|
app.run(debug=True)
|
|
429
425
|
'''
|
|
430
426
|
|
|
@@ -2,7 +2,7 @@ from setuptools import setup, find_packages
|
|
|
2
2
|
|
|
3
3
|
setup(
|
|
4
4
|
name='flask-core-utils',
|
|
5
|
-
version='2.
|
|
5
|
+
version='2.2.0',
|
|
6
6
|
packages=find_packages(),
|
|
7
7
|
description='Standard utility components and scaffolding for Flask applications',
|
|
8
8
|
long_description=open('README.md', encoding='utf-8').read(),
|
|
File without changes
|
|
File without changes
|
{flask_core_utils-2.0.0 → flask_core_utils-2.2.0}/flask_core_utils.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|