Начал работать над задачами в проектах, сделал файл конфигурации для задания логина и пароля от почты сайта и задания ключа шифрования

This commit is contained in:
Andrei 2023-02-10 23:55:51 +05:00
parent 1239819eca
commit 03b523bea8
10 changed files with 179 additions and 29 deletions

17
data/proof_to_quests.py Normal file
View File

@ -0,0 +1,17 @@
import sqlalchemy
from flask_login import UserMixin
from datetime import datetime
from .db_session import SqlAlchemyBase
class Proofs(SqlAlchemyBase, UserMixin):
__tablename__ = 'proofs'
id = sqlalchemy.Column(sqlalchemy.Integer, primary_key=True, autoincrement=True)
quest = sqlalchemy.Column(sqlalchemy.Integer, sqlalchemy.ForeignKey("quests.id"), nullable=True, default=None)
file = sqlalchemy.Column(sqlalchemy.Integer, sqlalchemy.ForeignKey("files.id"), nullable=True, default=None)
creator = sqlalchemy.Column(sqlalchemy.Integer, sqlalchemy.ForeignKey("users.id"), nullable=True,
default=None)
date_create = sqlalchemy.Column(sqlalchemy.DateTime, default=datetime.now())
date_edit = sqlalchemy.Column(sqlalchemy.DateTime, default=datetime.now())

View File

@ -1,6 +1,6 @@
import sqlalchemy import sqlalchemy
from flask_login import UserMixin from flask_login import UserMixin
from datetime import date from datetime import datetime
from .db_session import SqlAlchemyBase from .db_session import SqlAlchemyBase
@ -13,6 +13,6 @@ class Quests(SqlAlchemyBase, UserMixin):
creator = sqlalchemy.Column(sqlalchemy.Integer, sqlalchemy.ForeignKey("users.id"), nullable=True, default=None) creator = sqlalchemy.Column(sqlalchemy.Integer, sqlalchemy.ForeignKey("users.id"), nullable=True, default=None)
name = sqlalchemy.Column(sqlalchemy.String, nullable=False) name = sqlalchemy.Column(sqlalchemy.String, nullable=False)
description = sqlalchemy.Column(sqlalchemy.String, nullable=True) description = sqlalchemy.Column(sqlalchemy.String, nullable=True)
date_create = sqlalchemy.Column(sqlalchemy.DateTime, default=date.today()) date_create = sqlalchemy.Column(sqlalchemy.DateTime, default=datetime.now())
deadline = sqlalchemy.Column(sqlalchemy.DateTime, default=date.today()) deadline = sqlalchemy.Column(sqlalchemy.DateTime, default=datetime.now())
realized = sqlalchemy.Column(sqlalchemy.Boolean, default=False) realized = sqlalchemy.Column(sqlalchemy.Boolean, default=False)

View File

@ -1,4 +1,5 @@
import smtplib import smtplib
from json import loads
from email.message import EmailMessage from email.message import EmailMessage
from data.roles import Roles from data.roles import Roles
from data.users import User from data.users import User
@ -22,8 +23,9 @@ def check_password(password=''):
def mail(msg, to, topic='Подтверждение почты'): def mail(msg, to, topic='Подтверждение почты'):
file = open('mail.incepted', 'r', encoding='utf-8').readline().split() with open('incepted.config', 'r', encoding='utf-8').read() as file:
login, password = file[0], file[1] file = loads(file)
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"
em = EmailMessage() em = EmailMessage()

22
main.py
View File

@ -9,6 +9,7 @@ from werkzeug.datastructures import CombinedMultiDict
from werkzeug.utils import redirect from werkzeug.utils import redirect
from itsdangerous import URLSafeTimedSerializer, SignatureExpired from itsdangerous import URLSafeTimedSerializer, SignatureExpired
from sqlalchemy import or_ 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 from functions import check_password, mail, init_db_default, get_projects_data, get_user_data, save_project_logo
from forms.edit_profile import EditProfileForm from forms.edit_profile import EditProfileForm
@ -28,7 +29,10 @@ from waitress import serve
from data import db_session from data import db_session
app = Flask(__name__) app = Flask(__name__)
key = 'test_secret_key' with open('incepted.config', 'r', encoding='utf-8') as file:
file = file.read()
file = loads(file)
key = file["encrypt_key"]
app.config['SECRET_KEY'] = key app.config['SECRET_KEY'] = key
csrf = CSRFProtect(app) csrf = CSRFProtect(app)
s = URLSafeTimedSerializer(key) s = URLSafeTimedSerializer(key)
@ -83,7 +87,7 @@ def edit_project(id_project):
current_project.name = form.name.data current_project.name = form.name.data
current_project.description = form.description.data current_project.description = form.description.data
data_session.commit() data_session.commit()
return redirect(f'/project/{current_project.id}/edit') return redirect(f'/project/{current_project.id}')
if form.del_photo.data: if form.del_photo.data:
os.remove(current_project.photo) os.remove(current_project.photo)
current_project.photo = 'static/images/none_project.png' current_project.photo = 'static/images/none_project.png'
@ -109,8 +113,9 @@ def project(id_project):
if current_project: if current_project:
staff = data_session.query(StaffProjects).filter(StaffProjects.project == current_project.id).all() staff = data_session.query(StaffProjects).filter(StaffProjects.project == current_project.id).all()
if current_user.id == current_project.creator or current_user.id in list(map(lambda x: x.user, staff)): if current_user.id == current_project.creator or current_user.id in list(map(lambda x: x.user, staff)):
staff = list(map(lambda x: get_user_data(x), data_session.query(User).filter(
return render_template('project.html', project=current_project, title=current_project.name) User.id.in_(list(map(lambda x: x.user, staff)))).all())) if staff else []
return render_template('project.html', project=current_project, title=current_project.name, staff=staff)
else: else:
abort(403) abort(403)
else: else:
@ -180,6 +185,7 @@ def delete_project(id_project):
data_session.delete(i) data_session.delete(i)
if 'none_project' not in project_del.photo: if 'none_project' not in project_del.photo:
os.remove(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.delete(project_del)
data_session.commit() data_session.commit()
return redirect('/projects') return redirect('/projects')
@ -241,6 +247,7 @@ def new_project():
) )
data_session.add(new_staffer) data_session.add(new_staffer)
data_session.commit() data_session.commit()
os.mkdir(f'static/app_files/all_projects/{str(currnet_project.id)}')
return redirect('/projects') return redirect('/projects')
return render_template('new_project.html', title='Новый проект', form=form, list_users=list_users) return render_template('new_project.html', title='Новый проект', form=form, list_users=list_users)
else: else:
@ -302,7 +309,12 @@ def profile():
return render_template('profile.html', title='Профиль', form=form, return render_template('profile.html', title='Профиль', form=form,
message='Ошибка, пользователь ненайден') message='Ошибка, пользователь ненайден')
if form.email.data != current_user.email: if form.email.data != current_user.email:
pass token = s.dumps(form.email.data)
link_conf = url_for('confirmation', token=token, _external=True)
mail(f'Для изменения почты пройдите по ссылке: {link_conf}', form.email.data,
'Изменение почты')
user.activated = False
user.email = form.email.data
if form.photo.data: if form.photo.data:
with open(f'static/app_files/user_logo/{current_user.login}.png', 'wb') as file: with open(f'static/app_files/user_logo/{current_user.login}.png', 'wb') as file:
form.photo.data.save(file) form.photo.data.save(file)

Binary file not shown.

View File

@ -22,20 +22,10 @@
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
color: #dcb495 color: #dcb495;
#a8886f
#f5d3b8
#a65b1e
#d49d51
#face7d
#ffe8d6
#a8876b
#fff2e8
#c79b77
#d69d5c;
} }
.name_project { .name_project {
font-size: 3vw; font-size: 3vw !important;
} }
.edit_block { .edit_block {
display: flex; display: flex;
@ -53,3 +43,108 @@
height: 3vw; height: 3vw;
width: 3vw; width: 3vw;
} }
.collaborator_block {
width: 95%;
height: 25vw;
background-color: #EDCBB0;
border-radius: 2vw;
overflow-y: auto;
}
.staff_block {
margin: 20px;
}
.user {
width: 24vw;
height: 3.5vw;
background-color: #ffffff;
border: 2px solid #9E795A;
border-radius: 3vw;
margin-top: 5px;
display: flex;
align-items: center;
justify-content: flex-start;
flex-direction: row;
flex-wrap: no-wrap;
}
.user_logo {
margin-left: 3px;
width: 3vw;
height: 3vw;
border-radius: 5vw;
background-color: #000000;
}
.user_names {
margin-left: 9px;
margin-top: 10px;
overflow-x: auto;
color: #000000 !important;
}
.link_to_user {
width: 26vw;
height: 3.5vw;
display: flex;
align-items: center;
justify-content: flex-start;
flex-direction: row;
flex-wrap: no-wrap;
text-decoration: none;
}
.link_to_user:hover {
text-decoration: none;
}
.head_staff_block {
display: flex;
width: 30vw;
flex-direction: column;
align-items: center;
}
.header_title, .header_title_2 {
text-align: center;
color: #000000;
font-size: 3vw;
margin-bottom: 15px;
}
.header_title {
width: 100%;
}
.header_task_block {
width: 60vw;
height: 30vw;
display: flex;
flex-direction: column;
align-items: center;
}
.task_block {
background-color: #EDCBB0;
width: 95%;
height: 25vw;
border-radius: 2vw;
overflow-y: auto;
}
.task {
margin: 20px;
}
.body_block {
display: flex;
justify-content: space-evenly;
align-items: flex-start;
flex-direction: row;
}
.new_task_block {
width: 4.5vw;
height: 4.5vw;
}
.new_task_link {
width: 4.5vw;
height: 4.5vw;
}
.new_task_image {
width: 4.5vw;
height: 4.5vw;
}
.head_task {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
width: 60vw;
}

BIN
static/images/plus_b.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

BIN
static/images/plus_w.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

View File

@ -29,8 +29,8 @@
<a class="nav_chapter" href="/projects"> <a class="nav_chapter" href="/projects">
<p class="nav_chapter_text">Проекты</p> <p class="nav_chapter_text">Проекты</p>
</a> </a>
<a class="nav_chapter" href="/messages"> <a class="nav_chapter" href="/showcase">
<p class="nav_chapter_text">Сообщения</p> <p class="nav_chapter_text">Витрина</p>
</a> </a>
</div> </div>
</nav> </nav>

View File

@ -9,18 +9,42 @@
</div> </div>
<div class="brand_block"> <div class="brand_block">
<img class="project_logo" src="../{{project.photo}}"/> <img class="project_logo" src="../{{project.photo}}"/>
<p class="name_project">{{ project.name }}</p> <p class="name_project header_title">{{ project.name }}</p>
</div> </div>
<div class="notification_block"> <div class="notification_block">
</div> </div>
</div> </div>
<div class="body_block"> <div class="body_block">
<div class="head_staff_block">
<h3 class="header_title">Участники</h3>
<div class="collaborator_block">
<div class="staff_block"> <div class="staff_block">
{% for user in staff %}
<div class="user">
<a class="link_to_user" href="/user/{{ user.login }}">
<img class="user_logo" src="../{{user.photo}}">
<p class="user_names">{{user.name}}</p>
</a>
</div>
{% endfor %}
</div>
</div>
</div>
<div class="header_task_block">
<div class="head_task">
<h3 class="header_title_2">Задачи</h3>
<div class="new_task_block">
<a class="new_task_link" href="/">
<img class="new_task_image" src="../static/images/plus_b.png">
</a>
</div>
</div> </div>
<div class="task_block"> <div class="task_block">
<div class="task">
p
</div>
</div>
</div> </div>
</div> </div>
<div class="files_block"> <div class="files_block">