main.py 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610
  1. import datetime
  2. import os
  3. from flask import Flask, render_template, request, url_for
  4. from flask_login import login_user, current_user, LoginManager, logout_user, login_required
  5. from flask_wtf import CSRFProtect
  6. from flask_restful import abort
  7. from werkzeug.datastructures import CombinedMultiDict
  8. from werkzeug.utils import redirect
  9. from itsdangerous import URLSafeTimedSerializer, SignatureExpired
  10. from sqlalchemy import or_
  11. from json import loads
  12. from functions import check_password, mail, init_db_default, get_projects_data, get_user_data, save_project_logo, \
  13. overdue_quest_project, save_proof_quest, find_files_answer
  14. from forms.edit_profile import EditProfileForm
  15. from forms.login import LoginForm
  16. from forms.find_project import FindProjectForm
  17. from forms.register import RegisterForm
  18. from forms.project import ProjectForm
  19. from forms.recovery import RecoveryForm, NewPasswordForm
  20. from forms.conf_delete_project import DeleteProjectForm
  21. from forms.task import NewTask, AnswerTask
  22. from data.users import User
  23. from data.quests import Quests
  24. from data.answer import Answer
  25. from data.proof_file import FileProof
  26. from data.files import Files
  27. from data.projects import Projects
  28. from data.staff_projects import StaffProjects
  29. from waitress import serve
  30. from data import db_session
  31. app = Flask(__name__)
  32. with open('incepted.config', 'r', encoding='utf-8') as file:
  33. file = file.read()
  34. file = loads(file)
  35. key = file["encrypt_key"]
  36. app.config['SECRET_KEY'] = key
  37. csrf = CSRFProtect(app)
  38. s = URLSafeTimedSerializer(key)
  39. login_manager = LoginManager()
  40. login_manager.init_app(app)
  41. @app.route('/')
  42. def base():
  43. if not current_user.is_authenticated:
  44. return render_template('main.html', title='Главная')
  45. else:
  46. return redirect('/projects')
  47. @app.route('/project/<int:id_project>/file/<int:id_file>/delete')
  48. def delete_file(id_project, id_file):
  49. if current_user.is_authenticated:
  50. data_session = db_session.create_session()
  51. current_project = data_session.query(Projects).filter(Projects.id == id_project).first()
  52. current_file = data_session.query(Files).filter(Files.id == id_file).first()
  53. if current_project and current_file:
  54. if current_user.id in map(lambda x: x[0], data_session.query(StaffProjects.user).filter(
  55. StaffProjects.project == current_project.id).all()) or current_user.id == current_project.creator:
  56. current_proof = data_session.query(FileProof).filter(FileProof.file == id_file).all()
  57. os.remove(current_file.path)
  58. data_session.delete(current_file)
  59. if current_proof:
  60. quest = data_session.query(Answer.quest).filter(Answer.id == current_proof[0].answer).first()
  61. for i in current_proof:
  62. data_session.delete(i)
  63. data_session.commit()
  64. return redirect(f'/project/{current_project.id}/quest/{quest[0]}')
  65. data_session.commit()
  66. return redirect(f'/project/{current_project.id}')
  67. else:
  68. abort(403)
  69. else:
  70. abort(404)
  71. else:
  72. return redirect('/login')
  73. @app.route('/project/<int:id_project>/quest/<int:id_task>', methods=['GET', 'POST'])
  74. def task_project(id_project, id_task):
  75. if current_user.is_authenticated:
  76. data_session = db_session.create_session()
  77. current_project = data_session.query(Projects).filter(Projects.id == id_project).first()
  78. current_task = data_session.query(Quests).filter(Quests.id == id_task).first()
  79. if current_project and current_task and current_task.project == current_project.id:
  80. form = AnswerTask()
  81. current_answer = data_session.query(Answer).filter(Answer.quest == current_task.id).first()
  82. list_files = None
  83. if form.validate_on_submit():
  84. if form.deadline_date.data and form.deadline_time.data:
  85. deadline = datetime.datetime.combine(form.deadline_date.data, form.deadline_time.data)
  86. else:
  87. deadline = None
  88. current_task.deadline = deadline
  89. if current_answer:
  90. current_answer.text = form.text.data if form.text.data else None
  91. current_answer.date_edit = datetime.datetime.now()
  92. current_task.realized = form.realized.data
  93. data_session.commit()
  94. if form.file.data[0].filename:
  95. files = list(
  96. map(lambda x: save_proof_quest(current_project, x, current_user.id), form.file.data))
  97. for i in files:
  98. if not data_session.query(FileProof).filter(FileProof.answer == current_answer.id,
  99. FileProof.file == i).first():
  100. proof_file = FileProof(
  101. answer=current_answer.id,
  102. file=i
  103. )
  104. data_session.add(proof_file)
  105. data_session.commit()
  106. else:
  107. if form.file.data[0].filename:
  108. files = list(
  109. map(lambda x: save_proof_quest(current_project, x, current_user.id), form.file.data))
  110. else:
  111. files = False
  112. current_task.realized = form.realized.data
  113. current_answer = Answer(
  114. quest=current_task.id,
  115. text=form.text.data if form.text.data else None,
  116. creator=current_user.id,
  117. date_create=datetime.datetime.now(),
  118. date_edit=datetime.datetime.now()
  119. )
  120. data_session.add(current_answer)
  121. data_session.flush()
  122. data_session.refresh(current_answer)
  123. if files:
  124. for i in files:
  125. proof_file = FileProof(
  126. proof=current_answer.id,
  127. file=i
  128. )
  129. data_session.add(proof_file)
  130. data_session.commit()
  131. return redirect(f'/project/{current_project.id}')
  132. if current_answer:
  133. form.text.data = current_answer.text
  134. form.realized.data = current_task.realized
  135. files = data_session.query(FileProof).filter(FileProof.answer == current_answer.id).all()
  136. if files:
  137. list_files = list(map(lambda x: find_files_answer(x.file), files))
  138. if current_task.deadline and current_task.deadline:
  139. form.deadline_date.data = current_task.deadline.date()
  140. form.deadline_time.data = current_task.deadline.time()
  141. return render_template('answer.html', title='Решение', project=current_project, task=current_task,
  142. form=form, list_files=list_files)
  143. else:
  144. abort(404)
  145. else:
  146. return redirect('/login')
  147. @app.route('/project/<int:id_project>/quest/new', methods=['GET', 'POST'])
  148. def new_task_project(id_project):
  149. if current_user.is_authenticated:
  150. data_session = db_session.create_session()
  151. current_project = data_session.query(Projects).filter(Projects.id == id_project).first()
  152. if current_project:
  153. form = NewTask()
  154. if form.validate_on_submit():
  155. if form.deadline_date.data and form.deadline_time.data:
  156. deadline = datetime.datetime.combine(form.deadline_date.data, form.deadline_time.data)
  157. else:
  158. deadline = None
  159. quest = Quests(
  160. project=current_project.id,
  161. creator=current_user.id,
  162. name=form.name.data if form.name.data else None,
  163. description=form.description.data if form.description.data else None,
  164. date_create=datetime.datetime.now(),
  165. deadline=deadline,
  166. realized=False
  167. )
  168. data_session.add(quest)
  169. data_session.commit()
  170. return redirect(f'/project/{str(current_project.id)}')
  171. return render_template('new_task.html', title='Новая задача', form=form, porject=current_project)
  172. else:
  173. abort(404)
  174. else:
  175. return redirect('/login')
  176. @app.route('/project/<int:id_project>/edit', methods=['GET', 'POST'])
  177. def edit_project(id_project):
  178. if current_user.is_authenticated:
  179. data_session = db_session.create_session()
  180. current_project = data_session.query(Projects).filter(Projects.id == id_project).first()
  181. if current_project:
  182. staff = data_session.query(StaffProjects).filter(StaffProjects.project == current_project.id).all()
  183. if current_user.id == current_project.creator or current_user.id in list(map(lambda x: x.user, staff)):
  184. list_users = list(
  185. map(lambda x: get_user_data(x), data_session.query(User).filter(User.id != current_user.id).all()))
  186. staff = list(map(lambda x: get_user_data(x), data_session.query(User).filter(
  187. User.id.in_(list(map(lambda x: x.user, staff)))).all())) if staff else []
  188. form = ProjectForm()
  189. if form.save.data:
  190. new_staff = []
  191. for i in list_users:
  192. if request.form.getlist(f"choose_{i['login']}") and i['id'] != current_user.id:
  193. new_staff.append(i)
  194. if i not in staff:
  195. new_staffer = StaffProjects(
  196. user=i['id'],
  197. project=current_project.id,
  198. role='user',
  199. permission=3
  200. )
  201. data_session.add(new_staffer)
  202. data_session.commit()
  203. if sorted(new_staff, key=lambda x: x['id']) != sorted(staff, key=lambda x: x['id']):
  204. for i in staff:
  205. if i not in new_staff:
  206. data_session.delete(data_session.query(StaffProjects).filter(
  207. StaffProjects.user == i['id'], StaffProjects.project == current_project.id).first())
  208. data_session.commit()
  209. if form.logo.data:
  210. current_project.photo = save_project_logo(form.logo.data)
  211. data_session.commit()
  212. current_project.name = form.name.data
  213. current_project.description = form.description.data
  214. data_session.commit()
  215. return redirect(f'/project/{current_project.id}')
  216. if form.del_photo.data:
  217. os.remove(current_project.photo)
  218. current_project.photo = 'static/images/none_project.png'
  219. data_session.commit()
  220. return redirect(f'/project/{current_project.id}/edit')
  221. form.name.data = current_project.name
  222. form.description.data = current_project.description
  223. return render_template('edit_project.html', title='Изменение проекта', form=form, list_users=list_users,
  224. staff=staff, project=current_project)
  225. else:
  226. abort(403)
  227. else:
  228. abort(404)
  229. else:
  230. return redirect('/login')
  231. @app.route('/project/<int:id_project>')
  232. def project(id_project):
  233. if current_user.is_authenticated:
  234. data_session = db_session.create_session()
  235. current_project = data_session.query(Projects).filter(Projects.id == id_project).first()
  236. if current_project:
  237. staff = data_session.query(StaffProjects).filter(StaffProjects.project == current_project.id).all()
  238. if current_user.id == current_project.creator or current_user.id in list(map(lambda x: x.user, staff)):
  239. staff = list(map(lambda x: get_user_data(x), data_session.query(User).filter(
  240. User.id.in_(list(map(lambda x: x.user, staff)))).all())) if staff else []
  241. quests = data_session.query(Quests).filter(Quests.project == current_project.id).all()
  242. if quests:
  243. quests_sort = sorted(list(filter(lambda x: x.deadline is not None, quests)),
  244. key=lambda x: (x.realized, x.deadline))
  245. quests = list(filter(lambda x: x.realized == 0, quests_sort)) + list(
  246. filter(lambda x: x.deadline is None, quests)) + list(
  247. filter(lambda x: x.realized == 1, quests_sort))
  248. quests = list(map(lambda x: overdue_quest_project(x), quests))
  249. return render_template('project.html',
  250. project=current_project,
  251. title=current_project.name,
  252. staff=staff,
  253. quests=quests)
  254. else:
  255. abort(403)
  256. else:
  257. abort(404)
  258. else:
  259. return redirect('/login')
  260. @app.route('/recovery/confirmation/<token>', methods=['GET', 'POST'])
  261. def conf_recovery(token):
  262. try:
  263. user_email = s.loads(token, max_age=86400)
  264. data_session = db_session.create_session()
  265. user = data_session.query(User).filter(User.email == user_email).first()
  266. if user:
  267. form = NewPasswordForm()
  268. if form.validate_on_submit():
  269. if form.password.data != form.repeat_password.data:
  270. return render_template('recovery.html', title='Восстановление', form=form, recovery=0,
  271. message='Пароли не совпадают')
  272. status_password = check_password(form.password.data)
  273. if status_password != 'OK':
  274. return render_template('recovery.html', title='Восстановление', form=form, recovery=0,
  275. message=str(status_password))
  276. user.set_password(form.password.data)
  277. data_session.commit()
  278. mail(f'Для аккаунта {user.login}, успешно был обновлен пароль', user.email,
  279. 'Изменение пароля')
  280. return redirect('/login?message=Пароль обновлен')
  281. return render_template('recovery.html', title='Восстановление', form=form, recovery=0, message='')
  282. else:
  283. return redirect('/login?message=Пользователь не найден&danger=True')
  284. except SignatureExpired:
  285. return redirect('/login?message=Срок действия ссылки истек&danger=True')
  286. @app.route('/recovery', methods=['GET', 'POST'])
  287. def recovery():
  288. if not current_user.is_authenticated:
  289. form = RecoveryForm()
  290. if form.validate_on_submit():
  291. token = s.dumps(form.email.data)
  292. link_conf = url_for('conf_recovery', token=token, _external=True)
  293. mail(f'Для сбросы пароля пройдите по ссылке: {link_conf}', form.email.data,
  294. 'Восстановление доступа')
  295. return redirect('/login?message=Мы выслали ссылку для сброса вам на почту')
  296. return render_template('recovery.html', title='Восстановление пароля', form=form, recovery=True, message='')
  297. else:
  298. return redirect('/')
  299. @app.route('/project/<int:id_project>/delete', methods=['GET', 'POST'])
  300. def delete_project(id_project):
  301. if current_user.is_authenticated:
  302. data_session = db_session.create_session()
  303. project_del = data_session.query(Projects).filter(Projects.id == id_project).first()
  304. if project_del:
  305. if project_del.creator == current_user.id:
  306. form = DeleteProjectForm()
  307. if form.validate_on_submit():
  308. if form.conf.data != f'delete/{project_del.name}':
  309. return render_template('delete_project.html', title='Удаление проекта', form=form,
  310. project=project_del,
  311. message='Вы не правильно ввели фразу')
  312. staff = data_session.query(StaffProjects).filter(StaffProjects.project == id_project).all()
  313. for i in staff:
  314. data_session.delete(i)
  315. if 'none_project' not in project_del.photo:
  316. os.remove(project_del.photo)
  317. shutil.rmtree(f'static/app_files/all_projects/{str(project_del.id)}')
  318. data_session.delete(project_del)
  319. data_session.commit()
  320. return redirect('/projects')
  321. return render_template('delete_project.html', title='Удаление проекта', form=form, project=project_del,
  322. message='')
  323. else:
  324. abort(403)
  325. else:
  326. abort(404)
  327. else:
  328. return redirect('/login')
  329. @app.route('/user/<string:_login>', methods=['GET', 'POST'])
  330. def user_view(_login):
  331. if current_user.is_authenticated:
  332. data_session = db_session.create_session()
  333. user = data_session.query(User).filter(User.login == _login).first()
  334. if user:
  335. current_projects = data_session.query(Projects).filter(or_(Projects.creator == user.id, Projects.id.in_(
  336. list(map(lambda x: x[0], data_session.query(
  337. StaffProjects.project).filter(
  338. StaffProjects.user == user.id).all()))))).all()
  339. resp = list(map(lambda x: get_projects_data(x), current_projects))
  340. return render_template('user_view.html', title=user.name + ' ' + user.surname, user=user,
  341. list_projects=resp)
  342. else:
  343. abort(404)
  344. else:
  345. return redirect('/login')
  346. @app.route('/projects/new', methods=['GET', 'POST'])
  347. def new_project():
  348. if current_user.is_authenticated:
  349. form = ProjectForm()
  350. data_session = db_session.create_session()
  351. list_users = list(
  352. map(lambda x: get_user_data(x), data_session.query(User).filter(User.id != current_user.id).all()))
  353. if form.validate_on_submit():
  354. currnet_project = Projects(
  355. name=form.name.data,
  356. description=form.description.data,
  357. date_create=datetime.datetime.now(),
  358. creator=current_user.id
  359. )
  360. currnet_project.photo = save_project_logo(
  361. form.logo.data) if form.logo.data else 'static/images/none_project.png'
  362. data_session.add(currnet_project)
  363. data_session.flush()
  364. data_session.refresh(currnet_project)
  365. for i in list_users:
  366. if request.form.getlist(f"choose_{i['login']}") and i['id'] != current_user.id:
  367. new_staffer = StaffProjects(
  368. user=i['id'],
  369. project=currnet_project.id,
  370. role='user',
  371. permission=3
  372. )
  373. data_session.add(new_staffer)
  374. data_session.commit()
  375. os.mkdir(f'static/app_files/all_projects/{str(currnet_project.id)}')
  376. return redirect('/projects')
  377. return render_template('new_project.html', title='Новый проект', form=form, list_users=list_users)
  378. else:
  379. return redirect('/login')
  380. @app.route('/projects', methods=['GET', 'POST'])
  381. def projects():
  382. if current_user.is_authenticated:
  383. find = False
  384. form = FindProjectForm()
  385. data_session = db_session.create_session()
  386. resp = []
  387. current_projects = \
  388. data_session.query(Projects).filter(or_(Projects.creator == current_user.id,
  389. Projects.id.in_(
  390. list(map(lambda x: x[0],
  391. data_session.query(
  392. StaffProjects.project).filter(
  393. StaffProjects.user
  394. == current_user.id).all()))))).all()
  395. if form.validate_on_submit():
  396. new_resp = []
  397. for i in range(len(current_projects)):
  398. if str(form.project.data).lower().strip() in str(current_projects[i].name).lower().strip():
  399. new_resp.append(current_projects[i])
  400. current_projects = new_resp
  401. find = True
  402. resp = list(map(lambda x: get_projects_data(x), current_projects))
  403. return render_template('projects.html', title='Проекты', list_projects=resp, form=form, find=find)
  404. else:
  405. return redirect('/login')
  406. @app.route('/profile', methods=['GET', 'POST'])
  407. def profile():
  408. if current_user.is_authenticated:
  409. form = EditProfileForm(
  410. CombinedMultiDict((request.files, request.form)),
  411. email=current_user.email,
  412. name=current_user.name,
  413. surname=current_user.surname,
  414. about=current_user.about,
  415. birthday=current_user.birthday
  416. )
  417. if form.del_photo.data:
  418. data_session = db_session.create_session()
  419. user = data_session.query(User).filter(User.id == current_user.id).first()
  420. if not user:
  421. return render_template('profile.html', title='Профиль', form=form,
  422. message='Ошибка, пользователь ненайден')
  423. os.remove(current_user.photo)
  424. user.photo = 'static/images/none_logo.png'
  425. data_session.commit()
  426. if form.validate_on_submit():
  427. data_session = db_session.create_session()
  428. user = data_session.query(User).filter(User.id == current_user.id).first()
  429. if not user:
  430. return render_template('profile.html', title='Профиль', form=form,
  431. message='Ошибка, пользователь ненайден')
  432. if form.email.data != current_user.email:
  433. token = s.dumps(form.email.data)
  434. link_conf = url_for('confirmation', token=token, _external=True)
  435. mail(f'Для изменения почты пройдите по ссылке: {link_conf}', form.email.data,
  436. 'Изменение почты')
  437. user.activated = False
  438. user.email = form.email.data
  439. if form.photo.data:
  440. with open(f'static/app_files/user_logo/{current_user.login}.png', 'wb') as file:
  441. form.photo.data.save(file)
  442. user.photo = f'static/app_files/user_logo/{current_user.login}.png'
  443. user.name = form.name.data
  444. user.surname = form.surname.data
  445. user.about = form.about.data
  446. user.birthday = form.birthday.data
  447. data_session.commit()
  448. return redirect('/profile')
  449. return render_template('profile.html', title='Профиль', form=form, message='')
  450. else:
  451. return redirect('/login')
  452. @login_manager.user_loader
  453. def load_user(user_id):
  454. db_sess = db_session.create_session()
  455. return db_sess.query(User).get(user_id)
  456. @app.route('/login', methods=['GET', 'POST'])
  457. def login():
  458. if not current_user.is_authenticated:
  459. message = request.args.get('message') if request.args.get('message') else ''
  460. danger = request.args.get('danger') if request.args.get('danger') else False
  461. form = LoginForm()
  462. if form.validate_on_submit():
  463. data_session = db_session.create_session()
  464. user = data_session.query(User).filter(User.email == form.login.data).first()
  465. if not user:
  466. user = data_session.query(User).filter(User.login == form.login.data).first()
  467. if user and user.check_password(form.password.data):
  468. if user.activated:
  469. login_user(user, remember=form.remember_me.data)
  470. return redirect('/projects')
  471. else:
  472. return render_template('login.html',
  473. message="Ваша почта не подтверждена",
  474. danger=True,
  475. form=form)
  476. return render_template('login.html',
  477. message="Неправильный логин или пароль",
  478. danger=True,
  479. form=form)
  480. return render_template('login.html', title='Авторизация', form=form, message=message,
  481. danger=danger)
  482. else:
  483. return redirect('/projects')
  484. @app.route('/logout')
  485. @login_required
  486. def logout():
  487. logout_user()
  488. return redirect("/")
  489. @app.route('/register', methods=['GET', 'POST'])
  490. def register():
  491. if not current_user.is_authenticated:
  492. form = RegisterForm()
  493. if form.validate_on_submit():
  494. data_session = db_session.create_session()
  495. if data_session.query(User).filter(User.login == form.login.data).first():
  496. return render_template('register.html', form=form, message="Такой пользователь уже есть",
  497. title='Регистрация')
  498. if data_session.query(User).filter(User.email == form.email.data).first():
  499. return render_template('register.html', form=form, message="Такая почта уже есть", title='Регистрация')
  500. status_password = check_password(form.password.data)
  501. if status_password != 'OK':
  502. return render_template('register.html', form=form, message=status_password, title='Регистрация')
  503. user = User(
  504. email=form.email.data,
  505. name=form.name.data,
  506. login=form.login.data,
  507. activity=datetime.datetime.now(),
  508. data_reg=datetime.date.today(),
  509. photo='static/images/none_logo.png',
  510. role=1
  511. )
  512. user.set_password(form.password.data)
  513. data_session.add(user)
  514. data_session.commit()
  515. token = s.dumps(form.email.data)
  516. link_conf = url_for('confirmation', token=token, _external=True)
  517. mail(f'Для завершения регистрации пройдите по ссылке: {link_conf}', form.email.data,
  518. 'Подтверждение регистрации')
  519. return redirect('/login?message=Мы выслали ссылку для подтверждения почты')
  520. return render_template('register.html', form=form, message='', title='Регистрация')
  521. else:
  522. return redirect('/projects')
  523. @app.route('/confirmation/<token>')
  524. def confirmation(token):
  525. try:
  526. user_email = s.loads(token, max_age=86400)
  527. data_session = db_session.create_session()
  528. user = data_session.query(User).filter(User.email == user_email).first()
  529. if user:
  530. user.activated = True
  531. data_session.commit()
  532. return redirect('/login?message=Почта успешно подтверждена')
  533. else:
  534. return redirect('/login?message=Пользователь не найден&danger=True')
  535. except SignatureExpired:
  536. data_session = db_session.create_session()
  537. users = data_session.query(User).filter(
  538. User.activated == 0 and User.activated < datetime.datetime.now() - datetime.timedelta(days=1)).all()
  539. if users:
  540. list(map(lambda x: data_session.delete(x), users))
  541. data_session.commit()
  542. return redirect('/login?message=Срок действия ссылки истек, данные удалены&danger=True')
  543. @app.errorhandler(500)
  544. def internal_server_error(error):
  545. return render_template('page_error.html', title='Ошибка сервера', error='500', message='Технические шоколадки')
  546. @app.errorhandler(404)
  547. def page_not_found(error):
  548. return render_template('page_error.html', title='Страница не найдена', error='404', message='Страница не найдена')
  549. @app.errorhandler(403)
  550. def access_error(error):
  551. return render_template('page_error.html', title='Ошибка доступа', error='403', message='Доступ сюда запрещен')
  552. def main():
  553. db_path = 'db/incepted.db'
  554. db = os.path.exists(db_path)
  555. db_session.global_init(db_path)
  556. if not db:
  557. init_db_default()
  558. serve(app, host='0.0.0.0', port=5000)
  559. if __name__ == '__main__':
  560. main()