Merge website-branding feature and adjust for compatibility
- Resolved conflicts in models.py, app.py, and template files - Added branding checks to prevent errors when g.branding is None - Updated all template references to use conditional branding - Added BrandingSettings to migrations - Created branding uploads directory - Integrated branding with existing comment and task management features
This commit is contained in:
40
models.py
40
models.py
@@ -195,16 +195,18 @@ class User(db.Model):
|
||||
import pyotp
|
||||
self.two_factor_secret = pyotp.random_base32()
|
||||
return self.two_factor_secret
|
||||
|
||||
def get_2fa_uri(self):
|
||||
|
||||
def get_2fa_uri(self, issuer_name=None):
|
||||
"""Get the provisioning URI for QR code generation"""
|
||||
if not self.two_factor_secret:
|
||||
return None
|
||||
import pyotp
|
||||
totp = pyotp.TOTP(self.two_factor_secret)
|
||||
if issuer_name is None:
|
||||
issuer_name = "Time Tracker" # Default fallback
|
||||
return totp.provisioning_uri(
|
||||
name=self.email,
|
||||
issuer_name="TimeTrack"
|
||||
issuer_name=issuer_name
|
||||
)
|
||||
|
||||
def verify_2fa_token(self, token, allow_setup=False):
|
||||
@@ -267,6 +269,38 @@ class SystemSettings(db.Model):
|
||||
def __repr__(self):
|
||||
return f'<SystemSettings {self.key}={self.value}>'
|
||||
|
||||
class BrandingSettings(db.Model):
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
app_name = db.Column(db.String(100), nullable=False, default='Time Tracker')
|
||||
logo_filename = db.Column(db.String(255), nullable=True) # Filename of uploaded logo
|
||||
logo_alt_text = db.Column(db.String(255), nullable=True, default='Logo')
|
||||
favicon_filename = db.Column(db.String(255), nullable=True) # Filename of uploaded favicon
|
||||
primary_color = db.Column(db.String(7), nullable=True, default='#007bff') # Hex color
|
||||
|
||||
# Meta fields
|
||||
created_at = db.Column(db.DateTime, default=datetime.now)
|
||||
updated_at = db.Column(db.DateTime, default=datetime.now, onupdate=datetime.now)
|
||||
updated_by_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=True)
|
||||
|
||||
# Relationships
|
||||
updated_by = db.relationship('User', foreign_keys=[updated_by_id])
|
||||
|
||||
def __repr__(self):
|
||||
return f'<BrandingSettings {self.app_name}>'
|
||||
|
||||
@staticmethod
|
||||
def get_current():
|
||||
"""Get current branding settings or create defaults"""
|
||||
settings = BrandingSettings.query.first()
|
||||
if not settings:
|
||||
settings = BrandingSettings(
|
||||
app_name='Time Tracker',
|
||||
logo_alt_text='Application Logo'
|
||||
)
|
||||
db.session.add(settings)
|
||||
db.session.commit()
|
||||
return settings
|
||||
|
||||
class TimeEntry(db.Model):
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
arrival_time = db.Column(db.DateTime, nullable=False)
|
||||
|
||||
Reference in New Issue
Block a user