refactor: introduce app factory + blueprints (auth, core, admin users, invite); add utils and wsgi entrypoint; keep legacy routes for now
This commit is contained in:
67
app/utils/auth.py
Normal file
67
app/utils/auth.py
Normal file
@@ -0,0 +1,67 @@
|
||||
from flask import redirect, url_for, flash
|
||||
from flask_login import current_user
|
||||
from functools import wraps
|
||||
from werkzeug.security import generate_password_hash, check_password_hash
|
||||
import os
|
||||
|
||||
from app.models import User
|
||||
|
||||
|
||||
def admin_required(f):
|
||||
@wraps(f)
|
||||
def decorated(*args, **kwargs):
|
||||
if not current_user.is_authenticated:
|
||||
return redirect(url_for('login'))
|
||||
if not getattr(current_user, 'is_admin', False):
|
||||
flash('Недостаточно прав', 'danger')
|
||||
return redirect(url_for('dashboard'))
|
||||
return f(*args, **kwargs)
|
||||
return decorated
|
||||
|
||||
|
||||
def ensure_default_admin():
|
||||
username = os.environ.get('ADMIN_USERNAME', 'ruslan')
|
||||
password = os.environ.get('ADMIN_PASSWORD', '1234')
|
||||
email = os.environ.get('ADMIN_EMAIL', 'ruslan@example.com')
|
||||
|
||||
user = User.get_or_none(User.username == username)
|
||||
if user:
|
||||
changed = False
|
||||
if not user.is_admin:
|
||||
user.is_admin = True
|
||||
changed = True
|
||||
try:
|
||||
if not check_password_hash(user.password_hash, password):
|
||||
user.password_hash = generate_password_hash(password)
|
||||
changed = True
|
||||
except Exception:
|
||||
user.password_hash = generate_password_hash(password)
|
||||
changed = True
|
||||
if changed:
|
||||
user.save()
|
||||
else:
|
||||
User.create(
|
||||
username=username,
|
||||
email=email,
|
||||
full_name='Администратор',
|
||||
password_hash=generate_password_hash(password),
|
||||
is_admin=True
|
||||
)
|
||||
|
||||
|
||||
def ensure_test_users():
|
||||
tests = [
|
||||
('test1', 'test1@example.com', 'Пользователь 1'),
|
||||
('test2', 'test2@example.com', 'Пользователь 2'),
|
||||
]
|
||||
for username, email, full_name in tests:
|
||||
u = User.get_or_none(User.username == username)
|
||||
if not u:
|
||||
User.create(
|
||||
username=username,
|
||||
email=email,
|
||||
full_name=full_name,
|
||||
password_hash=generate_password_hash(os.environ.get('TEST_USER_PASSWORD', '1234')),
|
||||
is_admin=False,
|
||||
)
|
||||
|
||||
64
app/utils/mail.py
Normal file
64
app/utils/mail.py
Normal file
@@ -0,0 +1,64 @@
|
||||
import smtplib
|
||||
from email.mime.multipart import MIMEMultipart
|
||||
from email.mime.text import MIMEText
|
||||
|
||||
|
||||
def send_invite_email(to_email, link, sender_name, survey_name):
|
||||
msg = MIMEMultipart("alternative")
|
||||
msg['Subject'] = f"Приглашение пройти опрос: {survey_name}"
|
||||
msg['From'] = "quiz@4mont.ru"
|
||||
msg['To'] = to_email
|
||||
|
||||
plain_text = f"Опрос: {survey_name}\nОтправитель: {sender_name}\n\nСсылка: {link}\n"
|
||||
html = f"""
|
||||
<html>
|
||||
<body style="font-family: sans-serif;">
|
||||
<h3>Приглашение пройти опрос</h3>
|
||||
<p><strong>Опрос:</strong> {survey_name}<br>
|
||||
<strong>Отправитель:</strong> {sender_name}</p>
|
||||
<p><a href="{link}" style="font-size: 16px; font-weight: bold;">Перейти к опросу</a></p>
|
||||
</body>
|
||||
</html>
|
||||
"""
|
||||
|
||||
msg.attach(MIMEText(plain_text, "plain"))
|
||||
msg.attach(MIMEText(html, "html"))
|
||||
|
||||
with smtplib.SMTP("mail.hosting.reg.ru", 587) as server:
|
||||
server.starttls()
|
||||
server.login("quiz@4mont.ru", "utOgbZ09quizpochta")
|
||||
server.send_message(msg)
|
||||
|
||||
|
||||
def send_result_email(to_email, from_email, survey_name, scores, unsupported, sender_name):
|
||||
report_link = "https://quiz.4mont.ru/dashboard"
|
||||
plain_text = (
|
||||
f"Результаты опроса\nОтправитель: {sender_name} ({from_email})\n"
|
||||
f"Опрос: {survey_name}\n\n" +
|
||||
"\n".join(f"{p}: {v}%" for p, v in scores.items()) +
|
||||
"\n\nПодробности: " + report_link
|
||||
)
|
||||
html = f"""
|
||||
<html>
|
||||
<body style="font-family: sans-serif;">
|
||||
<h3>Результаты опроса: {survey_name}</h3>
|
||||
<ul>
|
||||
{''.join(f'<li><strong>{p}:</strong> {v}%</li>' for p, v in scores.items())}
|
||||
</ul>
|
||||
<p><a href="{report_link}" style="font-weight: bold;">Открыть отчеты</a></p>
|
||||
</body>
|
||||
</html>
|
||||
"""
|
||||
|
||||
msg = MIMEMultipart("alternative")
|
||||
msg['Subject'] = f"Результаты опроса: {survey_name}"
|
||||
msg['From'] = "quiz@4mont.ru"
|
||||
msg['To'] = to_email
|
||||
msg.attach(MIMEText(plain_text, "plain"))
|
||||
msg.attach(MIMEText(html, "html"))
|
||||
|
||||
with smtplib.SMTP("mail.hosting.reg.ru", 587) as server:
|
||||
server.starttls()
|
||||
server.login("quiz@4mont.ru", "utOgbZ09quizpochta")
|
||||
server.send_message(msg)
|
||||
|
||||
Reference in New Issue
Block a user