Backend aufgeräumt und Steckdosen-Einschaltfunktion behoben
- TAPO_PASSWORD in .env korrigiert (Agent045) - Unnötige Verzeichnisse entfernt (node_modules, archiv in backend/, etc.) - .gitignore erstellt um .env-Dateien zu schützen - Projektstruktur bereinigt (von 1.5MB auf 186KB reduziert) - Flask Web UI vollständig funktionsfähig 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
124
archiv/flask-backend/app/models.py
Normal file
124
archiv/flask-backend/app/models.py
Normal file
@@ -0,0 +1,124 @@
|
||||
from app import db
|
||||
import uuid
|
||||
from datetime import datetime, timedelta
|
||||
import jwt
|
||||
from config import Config
|
||||
import bcrypt
|
||||
|
||||
class User(db.Model):
|
||||
__tablename__ = 'user'
|
||||
|
||||
id = db.Column(db.String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
|
||||
username = db.Column(db.String(64), index=True, unique=True, nullable=False)
|
||||
display_name = db.Column(db.String(120))
|
||||
email = db.Column(db.String(120), index=True, unique=True, nullable=False)
|
||||
password_hash = db.Column(db.String(128), nullable=False)
|
||||
role = db.Column(db.String(20), default='user')
|
||||
|
||||
print_jobs = db.relationship('PrintJob', backref='user', lazy='dynamic', cascade='all, delete-orphan')
|
||||
sessions = db.relationship('Session', backref='user', lazy='dynamic', cascade='all, delete-orphan')
|
||||
|
||||
def set_password(self, password):
|
||||
"""Hash and set the user's password"""
|
||||
password_bytes = password.encode('utf-8')
|
||||
salt = bcrypt.gensalt()
|
||||
self.password_hash = bcrypt.hashpw(password_bytes, salt).decode('utf-8')
|
||||
|
||||
def check_password(self, password):
|
||||
"""Check if the provided password matches the stored hash"""
|
||||
password_bytes = password.encode('utf-8')
|
||||
stored_hash = self.password_hash.encode('utf-8')
|
||||
return bcrypt.checkpw(password_bytes, stored_hash)
|
||||
|
||||
def generate_token(self):
|
||||
"""Generate a JWT token for this user"""
|
||||
payload = {
|
||||
'user_id': self.id,
|
||||
'username': self.username,
|
||||
'email': self.email,
|
||||
'role': self.role,
|
||||
'exp': datetime.utcnow() + timedelta(seconds=Config.JWT_ACCESS_TOKEN_EXPIRES)
|
||||
}
|
||||
return jwt.encode(payload, Config.JWT_SECRET, algorithm='HS256')
|
||||
|
||||
@staticmethod
|
||||
def verify_token(token):
|
||||
"""Verify and decode a JWT token"""
|
||||
try:
|
||||
payload = jwt.decode(token, Config.JWT_SECRET, algorithms=['HS256'])
|
||||
return payload
|
||||
except:
|
||||
return None
|
||||
|
||||
|
||||
class Session(db.Model):
|
||||
__tablename__ = 'session'
|
||||
|
||||
id = db.Column(db.String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
|
||||
user_id = db.Column(db.String(36), db.ForeignKey('user.id', ondelete='CASCADE'), nullable=False)
|
||||
expires_at = db.Column(db.Integer, nullable=False)
|
||||
|
||||
|
||||
class Printer(db.Model):
|
||||
__tablename__ = 'printer'
|
||||
|
||||
id = db.Column(db.String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
|
||||
name = db.Column(db.String(120), nullable=False)
|
||||
description = db.Column(db.Text, nullable=False)
|
||||
status = db.Column(db.Integer, nullable=False, default=0) # 0: OPERATIONAL, 1: OUT_OF_ORDER
|
||||
|
||||
print_jobs = db.relationship('PrintJob', backref='printer', lazy='dynamic', cascade='all, delete-orphan')
|
||||
|
||||
|
||||
class PrintJob(db.Model):
|
||||
__tablename__ = 'printJob'
|
||||
|
||||
id = db.Column(db.String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
|
||||
printer_id = db.Column(db.String(36), db.ForeignKey('printer.id', ondelete='CASCADE'), nullable=False)
|
||||
user_id = db.Column(db.String(36), db.ForeignKey('user.id', ondelete='CASCADE'), nullable=False)
|
||||
start_at = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
|
||||
duration_in_minutes = db.Column(db.Integer, nullable=False)
|
||||
comments = db.Column(db.Text)
|
||||
aborted = db.Column(db.Boolean, nullable=False, default=False)
|
||||
abort_reason = db.Column(db.Text)
|
||||
|
||||
def get_end_time(self):
|
||||
return self.start_at + timedelta(minutes=self.duration_in_minutes)
|
||||
|
||||
def is_active(self):
|
||||
now = datetime.utcnow()
|
||||
return (not self.aborted and
|
||||
self.start_at <= now and
|
||||
now < self.get_end_time())
|
||||
|
||||
def get_remaining_time(self):
|
||||
if self.aborted:
|
||||
return 0
|
||||
|
||||
now = datetime.utcnow()
|
||||
if now < self.start_at:
|
||||
# Job hasn't started yet
|
||||
return self.duration_in_minutes * 60
|
||||
|
||||
end_time = self.get_end_time()
|
||||
if now >= end_time:
|
||||
# Job has ended
|
||||
return 0
|
||||
|
||||
# Job is ongoing
|
||||
remaining_seconds = (end_time - now).total_seconds()
|
||||
return int(remaining_seconds)
|
||||
|
||||
def to_dict(self):
|
||||
return {
|
||||
'id': self.id,
|
||||
'printer_id': self.printer_id,
|
||||
'user_id': self.user_id,
|
||||
'start_at': self.start_at.isoformat(),
|
||||
'duration_in_minutes': self.duration_in_minutes,
|
||||
'comments': self.comments,
|
||||
'aborted': self.aborted,
|
||||
'abort_reason': self.abort_reason,
|
||||
'remaining_time': self.get_remaining_time(),
|
||||
'is_active': self.is_active()
|
||||
}
|
||||
Reference in New Issue
Block a user