Add visibility column, access helpers and visible_to query to Set

This commit is contained in:
jessikitty committed 2026-09-25 00:44:26 +10:00
1 parent 19a2d7ad9e
commit eb796b6884
1 file changed
+65
+65
View File
@@ -24,6 +24,13 @@ class Set(db.Model):
image_url = db.Column(db.String(500)) # External URL (Brickset, etc.)
cover_image = db.Column(db.String(500)) # Uploaded cover image path
# Access control
# 'private' - owner and admins only
# 'shared' - owner, admins, and users listed in set_shares
# 'public' - every logged-in user
visibility = db.Column(db.String(10), nullable=False, default='private',
server_default='private', index=True)
# Metadata
user_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False)
created_at = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
@@ -35,9 +42,66 @@ class Set(db.Model):
cascade='all, delete-orphan')
extra_files = db.relationship('ExtraFile', back_populates='lego_set', lazy='dynamic',
cascade='all, delete-orphan', order_by='ExtraFile.uploaded_at.desc()')
shares = db.relationship('SetShare', lazy='dynamic', cascade='all, delete-orphan',
backref='lego_set')
def __repr__(self):
return f'<Set {self.set_number}: {self.set_name}>'
# ---- access control ---------------------------------------------------
def can_manage(self, user):
"""Edit, delete, upload to, or change sharing on this set."""
if user is None or not getattr(user, 'is_authenticated', False):
return False
return bool(user.is_admin) or self.user_id == user.id
def can_view(self, user):
"""See this set and its files."""
if user is None or not getattr(user, 'is_authenticated', False):
return False
if self.can_manage(user):
return True
if self.visibility == 'public':
return True
if self.visibility == 'shared':
from app.models.set_share import SetShare
return SetShare.query.filter_by(set_id=self.id,
user_id=user.id).first() is not None
return False
def shared_with(self):
"""Users this set is explicitly shared with."""
return [share.user for share in self.shares.all()]
@classmethod
def visible_to(cls, user):
"""Query restricted to sets `user` is allowed to see."""
from app.models.set_share import SetShare
query = cls.query
if user is None or not getattr(user, 'is_authenticated', False):
return query.filter(db.false())
if user.is_admin:
return query
shared_ids = db.session.query(SetShare.set_id).filter(
SetShare.user_id == user.id)
return query.filter(
db.or_(
cls.user_id == user.id,
cls.visibility == 'public',
db.and_(cls.visibility == 'shared', cls.id.in_(shared_ids)),
)
)
@property
def visibility_label(self):
return {'private': 'Private', 'shared': 'Shared',
'public': 'Public'}.get(self.visibility, self.visibility)
@property
def visibility_icon(self):
return {'private': 'bi-lock-fill', 'shared': 'bi-people-fill',
'public': 'bi-globe'}.get(self.visibility, 'bi-question')
def get_image(self):
"""Get the best available image (uploaded cover takes priority)."""
@@ -71,6 +135,7 @@ class Set(db.Model):
'piece_count': self.piece_count,
'image_url': self.image_url,
'is_moc': self.is_moc,
'visibility': self.visibility,
'moc_designer': self.moc_designer,
'moc_description': self.moc_description,
'instruction_count': self.instructions.count(),