From ab8286376182934c22370d9e0aa37abfdfe089d0 Mon Sep 17 00:00:00 2001 From: Andrei Date: Sun, 26 Feb 2023 17:31:52 +0500 Subject: [PATCH] =?UTF-8?q?=D0=9F=D0=BE=D0=BF=D1=80=D0=B0=D0=B2=D0=B8?= =?UTF-8?q?=D0=BB=20requirements.txt,=20=D1=81=D0=B4=D0=B5=D0=BB=D0=B0?= =?UTF-8?q?=D0=BB=20=D0=B2=D0=B0=D0=BB=D0=B8=D0=B4=D0=B0=D1=86=D0=B8=D1=8E?= =?UTF-8?q?=20=D0=B7=D0=B0=D0=B3=D1=80=D1=83=D0=B7=D0=BA=D0=B8=20=D0=BB?= =?UTF-8?q?=D0=BE=D0=B3=D0=BE=D1=82=D0=B8=D0=BF=D0=B0=20=D0=BF=D1=80=D0=BE?= =?UTF-8?q?=D0=B5=D0=BA=D1=82=D0=B0,=20=D1=81=D0=B4=D0=B5=D0=BB=D0=B0?= =?UTF-8?q?=D0=BB=20=D0=BB=D0=BE=D0=B3=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD?= =?UTF-8?q?=D0=B8=D0=B5=20=D0=BE=D1=88=D0=B8=D0=B1=D0=BE=D0=BA,=20=D0=B0?= =?UTF-8?q?=D0=B2=D1=82=D0=BE=D1=80=D0=B8=D0=B7=D0=B0=D1=86=D0=B8=D0=B8=20?= =?UTF-8?q?=D0=B8=20=D0=B2=D1=8B=D1=85=D0=BE=D0=B4=D0=B0,=20=D1=81=D0=B4?= =?UTF-8?q?=D0=B5=D0=BB=D0=B0=D0=BB=20=D0=BF=D0=BE=D0=BB=D0=BD=D0=BE=D0=B5?= =?UTF-8?q?=20=D1=83=D0=B4=D0=B0=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=BF?= =?UTF-8?q?=D1=80=D0=BE=D0=B5=D0=BA=D1=82=D0=B0=20=D0=B8=20=D0=B5=D0=B3?= =?UTF-8?q?=D0=BE=20=D1=81=D0=BE=D1=81=D1=82=D0=B0=D0=B2=D0=BB=D1=8F=D1=8E?= =?UTF-8?q?=D1=89=D0=B8=D1=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- forms/project.py | 3 ++- functions.py | 42 ++++++++++++++++++++++++++++++++++++++++-- logfiles/заглушка | 0 main.py | 39 ++++++++++++++++++++++----------------- requirements.txt | Bin 736 -> 776 bytes static/css/answer.css | 2 +- templates/answer.html | 23 +++++++++++++---------- tets.py | 5 ----- 8 files changed, 78 insertions(+), 36 deletions(-) create mode 100644 logfiles/заглушка delete mode 100644 tets.py diff --git a/forms/project.py b/forms/project.py index 3cd7205..5945049 100644 --- a/forms/project.py +++ b/forms/project.py @@ -1,4 +1,5 @@ from flask_wtf import FlaskForm +from flask_wtf.file import FileAllowed from wtforms import StringField, SubmitField, TextAreaField, FileField, MultipleFileField from wtforms.validators import DataRequired @@ -6,7 +7,7 @@ from wtforms.validators import DataRequired class ProjectForm(FlaskForm): name = StringField('Название', validators=[DataRequired()]) description = TextAreaField('Описание') - logo = FileField('Логотип') + logo = FileField('Логотип', validators=[FileAllowed(['jpg', 'png', 'bmp', 'ico', 'jpeg'], 'Только изображения')]) submit = SubmitField('Создать') del_photo = SubmitField('Удалить фотографию') save = SubmitField('Сохранить') diff --git a/functions.py b/functions.py index e41d13a..09fe82f 100644 --- a/functions.py +++ b/functions.py @@ -1,8 +1,14 @@ import datetime import os +import shutil import smtplib from json import loads from email.message import EmailMessage +from sqlalchemy import or_ + +from data.answer import Answer +from data.proof_file import FileProof +from data.quests import Quests from data.roles import Roles from data.users import User from data.staff_projects import StaffProjects @@ -27,8 +33,8 @@ def check_password(password=''): def mail(msg, to, topic='Подтверждение почты'): - with open('incepted.config', 'r', encoding='utf-8').read() as file: - file = loads(file) + with open('incepted.config', 'r', encoding='utf-8') as file: + file = loads(file.read()) login, password = file["mail_login"], file["mail_password"] email_server = "smtp.yandex.ru" sender = "incepted@yandex.ru" @@ -182,3 +188,35 @@ def file_tree(path): h += 1 data_session.close() return tree + + +def delete_file_proof_data(file_proof, data_session): + file = data_session.query(Files).filter(Files.id == file_proof.file).first() + data_session.delete(file) + + +def delete_answer_data(answer, data_session): + file_proofs = data_session.query(FileProof).filter(FileProof.answer == answer.id).all() + list(map(lambda file: delete_file_proof_data(file, data_session), file_proofs)) + list(map(data_session.delete, file_proofs)) + + +def delete_quest_data(quest, data_session): + answers = data_session.query(Answer).filter(Answer.quest == quest.id).all() + list(map(lambda answer: delete_answer_data(answer, data_session), answers)) + list(map(data_session.delete, answers)) + + +def delete_project_data(project, data_session): + staff = data_session.query(StaffProjects).filter(StaffProjects.project == project.id).all() + list(map(data_session.delete, staff)) + if 'none_project' not in project.photo: + os.remove(project.photo) + quests = data_session.query(Quests).filter(Quests.project == project.id).all() + list(map(lambda quest: delete_quest_data(quest, data_session), quests)) + list(map(data_session.delete, quests)) + list(map(data_session.delete, + data_session.query(Files).filter(Files.path.contains(f'all_projects/{str(project.id)}/')).all())) + shutil.rmtree(f'static/app_files/all_projects/{str(project.id)}') + data_session.delete(project) + data_session.commit() diff --git a/logfiles/заглушка b/logfiles/заглушка new file mode 100644 index 0000000..e69de29 diff --git a/main.py b/main.py index 4c6d80b..d9adbf0 100644 --- a/main.py +++ b/main.py @@ -1,5 +1,7 @@ import datetime import os +import logging +import shutil from flask import Flask, render_template, request, url_for from flask_login import login_user, current_user, LoginManager, logout_user, login_required @@ -12,7 +14,7 @@ from sqlalchemy import or_ from json import loads from functions import check_password, mail, init_db_default, get_projects_data, get_user_data, save_project_logo, \ - overdue_quest_project, save_proof_quest, find_files_answer, file_tree + overdue_quest_project, save_proof_quest, find_files_answer, file_tree, delete_project_data from forms.edit_profile import EditProfileForm from forms.login import LoginForm from forms.find_project import FindProjectForm @@ -38,6 +40,8 @@ with open('incepted.config', 'r', encoding='utf-8') as file: file = loads(file) key = file["encrypt_key"] app.config['SECRET_KEY'] = key +logging.basicConfig(level=logging.INFO, filename="logfiles/main.log", format="%(asctime)s %(levelname)s %(message)s", + encoding='utf-8') csrf = CSRFProtect(app) s = URLSafeTimedSerializer(key) login_manager = LoginManager() @@ -100,7 +104,7 @@ def task_project(id_project, id_task): deadline = None current_task.deadline = deadline if current_answer: - current_answer.text = form.text.data if form.text.data else None + current_answer.text = form.text.data current_answer.date_edit = datetime.datetime.now() current_task.realized = form.realized.data data_session.commit() @@ -125,7 +129,7 @@ def task_project(id_project, id_task): current_task.realized = form.realized.data current_answer = Answer( quest=current_task.id, - text=form.text.data if form.text.data else None, + text=form.text.data, creator=current_user.id, date_create=datetime.datetime.now(), date_edit=datetime.datetime.now() @@ -136,19 +140,19 @@ def task_project(id_project, id_task): if files: for i in files: proof_file = FileProof( - proof=current_answer.id, + answer=current_answer.id, file=i ) data_session.add(proof_file) data_session.commit() return redirect(f'/project/{current_project.id}') - if current_answer: + if current_answer and request.method == 'GET': form.text.data = current_answer.text form.realized.data = current_task.realized files = data_session.query(FileProof).filter(FileProof.answer == current_answer.id).all() if files: list_files = list(map(lambda x: find_files_answer(x.file), files)) - if current_task.deadline and current_task.deadline: + if current_task.deadline and current_task.deadline and request.method == 'GET': form.deadline_date.data = current_task.deadline.date() form.deadline_time.data = current_task.deadline.time() return render_template('answer.html', title='Решение', project=current_project, task=current_task, @@ -271,6 +275,7 @@ def project(id_project): if form_file.file.data[0].filename: files = list( map(lambda x: save_proof_quest(current_project, x, current_user.id), form_file.file.data)) + return redirect(f'/project/{str(current_project.id)}') return render_template('project.html', project=current_project, title=current_project.name, @@ -338,18 +343,11 @@ def delete_project(id_project): if project_del.creator == current_user.id: form = DeleteProjectForm() if form.validate_on_submit(): - if form.conf.data != f'delete/{project_del.name}': + if str(form.conf.data).lower().strip() != f'delete/{str(project_del.name)}'.lower().strip(): return render_template('delete_project.html', title='Удаление проекта', form=form, project=project_del, message='Вы не правильно ввели фразу') - staff = data_session.query(StaffProjects).filter(StaffProjects.project == id_project).all() - for i in staff: - data_session.delete(i) - if 'none_project' not in project_del.photo: - os.remove(project_del.photo) - shutil.rmtree(f'static/app_files/all_projects/{str(project_del.id)}') - data_session.delete(project_del) - data_session.commit() + delete_project_data(project_del, data_session) return redirect('/projects') return render_template('delete_project.html', title='Удаление проекта', form=form, project=project_del, message='') @@ -512,6 +510,7 @@ def login(): if user and user.check_password(form.password.data): if user.activated: login_user(user, remember=form.remember_me.data) + logging.info(f'{user.login} logged in') return redirect('/projects') else: return render_template('login.html', @@ -531,6 +530,7 @@ def login(): @app.route('/logout') @login_required def logout(): + logging.info(f'{current_user.login} logged out') logout_user() return redirect("/") @@ -565,6 +565,7 @@ def register(): link_conf = url_for('confirmation', token=token, _external=True) mail(f'Для завершения регистрации пройдите по ссылке: {link_conf}', form.email.data, 'Подтверждение регистрации') + logging.info(f'{form.login.data} was registered') return redirect('/login?message=Мы выслали ссылку для подтверждения почты') return render_template('register.html', form=form, message='', title='Регистрация') else: @@ -580,6 +581,7 @@ def confirmation(token): if user: user.activated = True data_session.commit() + logging.info(f'{user.login} has been confirmed') return redirect('/login?message=Почта успешно подтверждена') else: return redirect('/login?message=Пользователь не найден&danger=True') @@ -614,8 +616,11 @@ def main(): db_session.global_init(db_path) if not db: init_db_default() - serve(app, host='0.0.0.0', port=5000) + serve(app, host='0.0.0.0', port=5000, threads=10) if __name__ == '__main__': - main() + try: + main() + except Exception as error: + logging.warning(f'{error}') diff --git a/requirements.txt b/requirements.txt index dcd1a72ad6c92b0d38cc57cb7c6477424ba32cd0..9a2be68958574b37c82f85c6031cf10315e7bc81 100644 GIT binary patch delta 23 fcmaFB+QByA5~mMCK0`V~CPUuD>9QLy2rvNvUg`(1 delta 10 RcmeBRd%!y3(#BtWOaK}E1d#v$ diff --git a/static/css/answer.css b/static/css/answer.css index 29c54c3..2f2cadf 100644 --- a/static/css/answer.css +++ b/static/css/answer.css @@ -170,7 +170,7 @@ form { max-height: 20vw; } .form_text_one { - width: 100%; + width: 200%; } .files_block { width: 100%; diff --git a/templates/answer.html b/templates/answer.html index 38c412f..7bf11bf 100644 --- a/templates/answer.html +++ b/templates/answer.html @@ -33,10 +33,13 @@
- {% if current_user.id == project.creator or task.creator == current_user.id or file['user'] == current_user.id %} -

Удалить

+ {% if current_user.id == project.creator or task.creator == current_user.id or + file['user'] == current_user.id %} +

Удалить

{% endif %} -

Скачать

+ +

Скачать

@@ -45,17 +48,17 @@ {% endif %} -
- - {{ form.text(class="input_data text_data", type="text", id="text_data", placeholder='your answer') }} - {% for error in form.text.errors %} - - {% endfor %} -
{{ form.hidden_tag() }} +
+ + {{ form.text(class="input_data text_data", type="text", id="text_data", placeholder='your answer') }} + {% for error in form.text.errors %} + + {% endfor %} +
diff --git a/tets.py b/tets.py deleted file mode 100644 index b37f3c4..0000000 --- a/tets.py +++ /dev/null @@ -1,5 +0,0 @@ -import os - -path = os.listdir('.') -print(path) -print(os.path.isdir(path[6])) \ No newline at end of file