Поправил requirements.txt, сделал валидацию загрузки логотипа проекта, сделал логирование ошибок, авторизации и выхода, сделал полное удаление проекта и его составляющих

This commit is contained in:
Andrei 2023-02-26 17:31:52 +05:00
parent 3a7b651960
commit ab82863761
8 changed files with 78 additions and 36 deletions

View File

@ -1,4 +1,5 @@
from flask_wtf import FlaskForm from flask_wtf import FlaskForm
from flask_wtf.file import FileAllowed
from wtforms import StringField, SubmitField, TextAreaField, FileField, MultipleFileField from wtforms import StringField, SubmitField, TextAreaField, FileField, MultipleFileField
from wtforms.validators import DataRequired from wtforms.validators import DataRequired
@ -6,7 +7,7 @@ from wtforms.validators import DataRequired
class ProjectForm(FlaskForm): class ProjectForm(FlaskForm):
name = StringField('Название', validators=[DataRequired()]) name = StringField('Название', validators=[DataRequired()])
description = TextAreaField('Описание') description = TextAreaField('Описание')
logo = FileField('Логотип') logo = FileField('Логотип', validators=[FileAllowed(['jpg', 'png', 'bmp', 'ico', 'jpeg'], 'Только изображения')])
submit = SubmitField('Создать') submit = SubmitField('Создать')
del_photo = SubmitField('Удалить фотографию') del_photo = SubmitField('Удалить фотографию')
save = SubmitField('Сохранить') save = SubmitField('Сохранить')

View File

@ -1,8 +1,14 @@
import datetime import datetime
import os import os
import shutil
import smtplib import smtplib
from json import loads from json import loads
from email.message import EmailMessage 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.roles import Roles
from data.users import User from data.users import User
from data.staff_projects import StaffProjects from data.staff_projects import StaffProjects
@ -27,8 +33,8 @@ def check_password(password=''):
def mail(msg, to, topic='Подтверждение почты'): def mail(msg, to, topic='Подтверждение почты'):
with open('incepted.config', 'r', encoding='utf-8').read() as file: with open('incepted.config', 'r', encoding='utf-8') as file:
file = loads(file) file = loads(file.read())
login, password = file["mail_login"], file["mail_password"] login, password = file["mail_login"], file["mail_password"]
email_server = "smtp.yandex.ru" email_server = "smtp.yandex.ru"
sender = "incepted@yandex.ru" sender = "incepted@yandex.ru"
@ -182,3 +188,35 @@ def file_tree(path):
h += 1 h += 1
data_session.close() data_session.close()
return tree 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()

View File

39
main.py
View File

@ -1,5 +1,7 @@
import datetime import datetime
import os import os
import logging
import shutil
from flask import Flask, render_template, request, url_for from flask import Flask, render_template, request, url_for
from flask_login import login_user, current_user, LoginManager, logout_user, login_required 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 json import loads
from functions import check_password, mail, init_db_default, get_projects_data, get_user_data, save_project_logo, \ 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.edit_profile import EditProfileForm
from forms.login import LoginForm from forms.login import LoginForm
from forms.find_project import FindProjectForm from forms.find_project import FindProjectForm
@ -38,6 +40,8 @@ with open('incepted.config', 'r', encoding='utf-8') as file:
file = loads(file) file = loads(file)
key = file["encrypt_key"] key = file["encrypt_key"]
app.config['SECRET_KEY'] = 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) csrf = CSRFProtect(app)
s = URLSafeTimedSerializer(key) s = URLSafeTimedSerializer(key)
login_manager = LoginManager() login_manager = LoginManager()
@ -100,7 +104,7 @@ def task_project(id_project, id_task):
deadline = None deadline = None
current_task.deadline = deadline current_task.deadline = deadline
if current_answer: 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_answer.date_edit = datetime.datetime.now()
current_task.realized = form.realized.data current_task.realized = form.realized.data
data_session.commit() data_session.commit()
@ -125,7 +129,7 @@ def task_project(id_project, id_task):
current_task.realized = form.realized.data current_task.realized = form.realized.data
current_answer = Answer( current_answer = Answer(
quest=current_task.id, quest=current_task.id,
text=form.text.data if form.text.data else None, text=form.text.data,
creator=current_user.id, creator=current_user.id,
date_create=datetime.datetime.now(), date_create=datetime.datetime.now(),
date_edit=datetime.datetime.now() date_edit=datetime.datetime.now()
@ -136,19 +140,19 @@ def task_project(id_project, id_task):
if files: if files:
for i in files: for i in files:
proof_file = FileProof( proof_file = FileProof(
proof=current_answer.id, answer=current_answer.id,
file=i file=i
) )
data_session.add(proof_file) data_session.add(proof_file)
data_session.commit() data_session.commit()
return redirect(f'/project/{current_project.id}') return redirect(f'/project/{current_project.id}')
if current_answer: if current_answer and request.method == 'GET':
form.text.data = current_answer.text form.text.data = current_answer.text
form.realized.data = current_task.realized form.realized.data = current_task.realized
files = data_session.query(FileProof).filter(FileProof.answer == current_answer.id).all() files = data_session.query(FileProof).filter(FileProof.answer == current_answer.id).all()
if files: if files:
list_files = list(map(lambda x: find_files_answer(x.file), 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_date.data = current_task.deadline.date()
form.deadline_time.data = current_task.deadline.time() form.deadline_time.data = current_task.deadline.time()
return render_template('answer.html', title='Решение', project=current_project, task=current_task, 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: if form_file.file.data[0].filename:
files = list( files = list(
map(lambda x: save_proof_quest(current_project, x, current_user.id), form_file.file.data)) 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', return render_template('project.html',
project=current_project, project=current_project,
title=current_project.name, title=current_project.name,
@ -338,18 +343,11 @@ def delete_project(id_project):
if project_del.creator == current_user.id: if project_del.creator == current_user.id:
form = DeleteProjectForm() form = DeleteProjectForm()
if form.validate_on_submit(): 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, return render_template('delete_project.html', title='Удаление проекта', form=form,
project=project_del, project=project_del,
message='Вы не правильно ввели фразу') message='Вы не правильно ввели фразу')
staff = data_session.query(StaffProjects).filter(StaffProjects.project == id_project).all() delete_project_data(project_del, data_session)
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()
return redirect('/projects') return redirect('/projects')
return render_template('delete_project.html', title='Удаление проекта', form=form, project=project_del, return render_template('delete_project.html', title='Удаление проекта', form=form, project=project_del,
message='') message='')
@ -512,6 +510,7 @@ def login():
if user and user.check_password(form.password.data): if user and user.check_password(form.password.data):
if user.activated: if user.activated:
login_user(user, remember=form.remember_me.data) login_user(user, remember=form.remember_me.data)
logging.info(f'{user.login} logged in')
return redirect('/projects') return redirect('/projects')
else: else:
return render_template('login.html', return render_template('login.html',
@ -531,6 +530,7 @@ def login():
@app.route('/logout') @app.route('/logout')
@login_required @login_required
def logout(): def logout():
logging.info(f'{current_user.login} logged out')
logout_user() logout_user()
return redirect("/") return redirect("/")
@ -565,6 +565,7 @@ def register():
link_conf = url_for('confirmation', token=token, _external=True) link_conf = url_for('confirmation', token=token, _external=True)
mail(f'Для завершения регистрации пройдите по ссылке: {link_conf}', form.email.data, mail(f'Для завершения регистрации пройдите по ссылке: {link_conf}', form.email.data,
'Подтверждение регистрации') 'Подтверждение регистрации')
logging.info(f'{form.login.data} was registered')
return redirect('/login?message=Мы выслали ссылку для подтверждения почты') return redirect('/login?message=Мы выслали ссылку для подтверждения почты')
return render_template('register.html', form=form, message='', title='Регистрация') return render_template('register.html', form=form, message='', title='Регистрация')
else: else:
@ -580,6 +581,7 @@ def confirmation(token):
if user: if user:
user.activated = True user.activated = True
data_session.commit() data_session.commit()
logging.info(f'{user.login} has been confirmed')
return redirect('/login?message=Почта успешно подтверждена') return redirect('/login?message=Почта успешно подтверждена')
else: else:
return redirect('/login?message=Пользователь не найден&danger=True') return redirect('/login?message=Пользователь не найден&danger=True')
@ -614,8 +616,11 @@ def main():
db_session.global_init(db_path) db_session.global_init(db_path)
if not db: if not db:
init_db_default() 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__': if __name__ == '__main__':
main() try:
main()
except Exception as error:
logging.warning(f'{error}')

Binary file not shown.

View File

@ -170,7 +170,7 @@ form {
max-height: 20vw; max-height: 20vw;
} }
.form_text_one { .form_text_one {
width: 100%; width: 200%;
} }
.files_block { .files_block {
width: 100%; width: 100%;

View File

@ -33,10 +33,13 @@
</div> </div>
<div class="file_buttons"> <div class="file_buttons">
<div class="btn-group file_buttons_groud"> <div class="btn-group file_buttons_groud">
{% 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
<a href="../file/{{ file.id }}/delete" class="btn btn-primary file_delete"><p class="button_text">Удалить</p></a> file['user'] == current_user.id %}
<a href="../file/{{ file.id }}/delete" class="btn btn-primary file_delete"><p
class="button_text">Удалить</p></a>
{% endif %} {% endif %}
<a href="../../../{{ file['path'] }}" download="" class="btn btn-primary file_download"><p class="button_text">Скачать</p></a> <a href="../../../{{ file['path'] }}" download="" class="btn btn-primary file_download">
<p class="button_text">Скачать</p></a>
</div> </div>
</div> </div>
</div> </div>
@ -45,17 +48,17 @@
</div> </div>
</div> </div>
{% endif %} {% endif %}
<div class="form_data bottom_data form_text_one">
<label class="form_label">{{ form.text.label }}</label>
{{ form.text(class="input_data text_data", type="text", id="text_data", placeholder='your answer') }}
{% for error in form.text.errors %}
<div class="alert alert-danger" role="alert">{{ error }}</div>
{% endfor %}
</div>
</div> </div>
<div class="decision_block"> <div class="decision_block">
<form action="" method="post" class="answer_form" enctype="multipart/form-data"> <form action="" method="post" class="answer_form" enctype="multipart/form-data">
{{ form.hidden_tag() }} {{ form.hidden_tag() }}
<div class="form_data bottom_data form_text_one">
<label class="form_label">{{ form.text.label }}</label>
{{ form.text(class="input_data text_data", type="text", id="text_data", placeholder='your answer') }}
{% for error in form.text.errors %}
<div class="alert alert-danger" role="alert">{{ error }}</div>
{% endfor %}
</div>
<div class="data_block"> <div class="data_block">
<div class="form_data bottom_data"> <div class="form_data bottom_data">
<label class="form_label">{{ form.file.label }}</label> <label class="form_label">{{ form.file.label }}</label>

View File

@ -1,5 +0,0 @@
import os
path = os.listdir('.')
print(path)
print(os.path.isdir(path[6]))