Add user auth, personal cabinet, admin panel and first admin bootstrap
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+58
-26
@@ -1,13 +1,24 @@
|
||||
import os
|
||||
from datetime import datetime, timezone
|
||||
|
||||
from flask import Flask
|
||||
from flask_login import LoginManager
|
||||
from flask_sqlalchemy import SQLAlchemy
|
||||
from dotenv import load_dotenv
|
||||
|
||||
load_dotenv()
|
||||
|
||||
db = SQLAlchemy()
|
||||
login_manager = LoginManager()
|
||||
login_manager.login_view = "auth.login"
|
||||
login_manager.login_message = "Войдите для доступа к этой странице."
|
||||
login_manager.login_message_category = "error"
|
||||
|
||||
|
||||
@login_manager.user_loader
|
||||
def load_user(user_id):
|
||||
from app.models import User
|
||||
|
||||
return db.session.get(User, int(user_id))
|
||||
|
||||
|
||||
def create_app():
|
||||
@@ -26,40 +37,61 @@ def create_app():
|
||||
os.makedirs(app.config["UPLOAD_FOLDER"], exist_ok=True)
|
||||
|
||||
db.init_app(app)
|
||||
login_manager.init_app(app)
|
||||
|
||||
from .routes import bp
|
||||
from .routes import bp as main_bp, cabinet_bp
|
||||
from .auth import bp as auth_bp
|
||||
from .admin import bp as admin_bp
|
||||
|
||||
app.register_blueprint(bp)
|
||||
app.register_blueprint(main_bp)
|
||||
app.register_blueprint(cabinet_bp)
|
||||
app.register_blueprint(auth_bp)
|
||||
app.register_blueprint(admin_bp)
|
||||
|
||||
register_cli(app)
|
||||
|
||||
with app.app_context():
|
||||
from app.models import Photo, User # noqa: F401
|
||||
|
||||
db.create_all()
|
||||
from app.bootstrap import create_first_admin, ensure_schema
|
||||
|
||||
ensure_schema()
|
||||
create_first_admin(app)
|
||||
|
||||
return app
|
||||
|
||||
|
||||
class Photo(db.Model):
|
||||
__tablename__ = "photos"
|
||||
def register_cli(app):
|
||||
@app.cli.command("create-admin")
|
||||
def create_admin_command():
|
||||
"""Create or update admin user interactively."""
|
||||
from getpass import getpass
|
||||
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
filename = db.Column(db.String(255), nullable=False)
|
||||
original_name = db.Column(db.String(255), nullable=False)
|
||||
file_size = db.Column(db.Integer, nullable=False, default=0)
|
||||
mime_type = db.Column(db.String(100), nullable=False, default="image/jpeg")
|
||||
created_at = db.Column(
|
||||
db.DateTime,
|
||||
nullable=False,
|
||||
default=lambda: datetime.now(timezone.utc),
|
||||
)
|
||||
from app.models import User
|
||||
|
||||
@property
|
||||
def url(self):
|
||||
return f"/uploads/{self.filename}"
|
||||
username = input("Username: ").strip()
|
||||
email = input("Email: ").strip()
|
||||
password = getpass("Password: ")
|
||||
password2 = getpass("Confirm password: ")
|
||||
|
||||
@property
|
||||
def size_human(self):
|
||||
size = self.file_size
|
||||
for unit in ("Б", "КБ", "МБ", "ГБ"):
|
||||
if size < 1024:
|
||||
return f"{size:.0f} {unit}" if unit == "Б" else f"{size:.1f} {unit}"
|
||||
size /= 1024
|
||||
return f"{size:.1f} ТБ"
|
||||
if not username or not email or not password:
|
||||
print("All fields are required.")
|
||||
return
|
||||
if password != password2:
|
||||
print("Passwords do not match.")
|
||||
return
|
||||
|
||||
user = User.query.filter_by(username=username).first()
|
||||
if user:
|
||||
user.email = email
|
||||
user.is_admin = True
|
||||
user.set_password(password)
|
||||
print(f"User '{username}' updated and promoted to admin.")
|
||||
else:
|
||||
user = User(username=username, email=email, is_admin=True)
|
||||
user.set_password(password)
|
||||
db.session.add(user)
|
||||
print(f"Admin '{username}' created.")
|
||||
|
||||
db.session.commit()
|
||||
|
||||
Reference in New Issue
Block a user