Add Flask-CORS and SocketIO for real-time updates, refactor database handling to use a temporary Flask app; improve error handling with @app.errorhandler decorators.

This commit is contained in:
2025-04-28 15:21:11 +02:00
parent 7a0533ac09
commit 0852ea070b
11 changed files with 1633 additions and 1224 deletions

112
models.py
View File

@@ -6,6 +6,8 @@ from flask_login import UserMixin
from datetime import datetime
from werkzeug.security import generate_password_hash, check_password_hash
from enum import Enum
import uuid as uuid_pkg
import os
db = SQLAlchemy()
@@ -43,30 +45,28 @@ user_thought_bookmark = db.Table('user_thought_bookmark',
db.Column('created_at', db.DateTime, default=datetime.utcnow)
)
class User(UserMixin, db.Model):
class User(db.Model, UserMixin):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(80), unique=True, nullable=False)
email = db.Column(db.String(120), unique=True, nullable=False)
password_hash = db.Column(db.String(128))
is_admin = db.Column(db.Boolean, default=False)
password = db.Column(db.String(512), nullable=False)
created_at = db.Column(db.DateTime, default=datetime.utcnow)
last_login = db.Column(db.DateTime)
avatar = db.Column(db.String(200))
bio = db.Column(db.Text)
is_active = db.Column(db.Boolean, default=True)
role = db.Column(db.String(20), default="user") # 'user', 'admin', 'moderator'
# Beziehungen
thoughts = db.relationship('Thought', backref='author', lazy=True)
comments = db.relationship('Comment', backref='author', lazy=True)
user_mindmaps = db.relationship('UserMindmap', backref='user', lazy=True)
mindmap_notes = db.relationship('MindmapNote', backref='user', lazy=True)
bookmarked_thoughts = db.relationship('Thought', secondary=user_thought_bookmark,
backref=db.backref('bookmarked_by', lazy='dynamic'))
# Relationships
threads = db.relationship('Thread', backref='creator', lazy=True)
messages = db.relationship('Message', backref='author', lazy=True)
projects = db.relationship('Project', backref='owner', lazy=True)
def __repr__(self):
return f'<User {self.username}>'
def set_password(self, password):
self.password_hash = generate_password_hash(password)
self.password = generate_password_hash(password)
def check_password(self, password):
return check_password_hash(self.password_hash, password)
return check_password_hash(self.password, password)
class Category(db.Model):
"""Wissenschaftliche Kategorien für die Gliederung der öffentlichen Mindmap"""
@@ -81,6 +81,9 @@ class Category(db.Model):
children = db.relationship('Category', backref=db.backref('parent', remote_side=[id]))
nodes = db.relationship('MindMapNode', backref='category', lazy=True)
def __repr__(self):
return f'<Category {self.name}>'
class MindMapNode(db.Model):
"""Öffentliche Mindmap-Knoten, die für alle Benutzer sichtbar sind"""
id = db.Column(db.Integer, primary_key=True)
@@ -92,7 +95,9 @@ class MindMapNode(db.Model):
created_at = db.Column(db.DateTime, default=datetime.utcnow)
created_by_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=True)
category_id = db.Column(db.Integer, db.ForeignKey('category.id'), nullable=True)
__table_args__ = {'extend_existing': True}
# Beziehungen für Baumstruktur (mehrere Eltern möglich)
parents = db.relationship(
'MindMapNode',
@@ -111,6 +116,20 @@ class MindMapNode(db.Model):
# Beziehung zum Ersteller
created_by = db.relationship('User', backref='created_nodes')
def __repr__(self):
return f'<MindMapNode {self.name}>'
def to_dict(self):
return {
'id': self.id,
'name': self.name,
'description': self.description,
'color_code': self.color_code,
'icon': self.icon,
'category_id': self.category_id,
'created_at': self.created_at.isoformat() if self.created_at else None
}
class UserMindmap(db.Model):
"""Benutzerspezifische Mindmap, die vom Benutzer personalisierbar ist"""
id = db.Column(db.Integer, primary_key=True)
@@ -227,4 +246,63 @@ class Comment(db.Model):
thought_id = db.Column(db.Integer, db.ForeignKey('thought.id'), nullable=False)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
created_at = db.Column(db.DateTime, default=datetime.utcnow)
last_modified = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
last_modified = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
# Thread model
class Thread(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(200), nullable=False)
description = db.Column(db.Text)
created_at = db.Column(db.DateTime, default=datetime.utcnow)
updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
# Relationships
messages = db.relationship('Message', backref='thread', lazy=True, cascade="all, delete-orphan")
def __repr__(self):
return f'<Thread {self.title}>'
# Message model
class Message(db.Model):
id = db.Column(db.Integer, primary_key=True)
content = db.Column(db.Text, nullable=False)
created_at = db.Column(db.DateTime, default=datetime.utcnow)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
thread_id = db.Column(db.Integer, db.ForeignKey('thread.id'), nullable=False)
role = db.Column(db.String(20), default="user") # 'user', 'assistant', 'system'
def __repr__(self):
return f'<Message {self.id} by {self.user_id}>'
# Project model
class Project(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(150), nullable=False)
description = db.Column(db.Text)
created_at = db.Column(db.DateTime, default=datetime.utcnow)
updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
category_id = db.Column(db.Integer, db.ForeignKey('category.id'))
# Relationships
documents = db.relationship('Document', backref='project', lazy=True, cascade="all, delete-orphan")
def __repr__(self):
return f'<Project {self.title}>'
# Document model
class Document(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(150), nullable=False)
content = db.Column(db.Text)
created_at = db.Column(db.DateTime, default=datetime.utcnow)
updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
project_id = db.Column(db.Integer, db.ForeignKey('project.id'), nullable=False)
filename = db.Column(db.String(150), nullable=True)
file_path = db.Column(db.String(300), nullable=True)
file_type = db.Column(db.String(50), nullable=True)
file_size = db.Column(db.Integer, nullable=True)
def __repr__(self):
return f'<Document {self.title}>'