Add folders with password sharing and email invites
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import uuid
|
||||
from datetime import datetime, timezone
|
||||
|
||||
from flask_login import UserMixin
|
||||
@@ -22,6 +23,7 @@ class User(UserMixin, db.Model):
|
||||
)
|
||||
|
||||
photos = db.relationship("Photo", backref="owner", lazy="dynamic")
|
||||
folders = db.relationship("Folder", backref="owner", lazy="dynamic")
|
||||
|
||||
def set_password(self, password):
|
||||
self.password_hash = generate_password_hash(password)
|
||||
@@ -43,6 +45,92 @@ class User(UserMixin, db.Model):
|
||||
return int(result or 0)
|
||||
|
||||
|
||||
class Folder(db.Model):
|
||||
__tablename__ = "folders"
|
||||
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
name = db.Column(db.String(120), nullable=False)
|
||||
owner_id = db.Column(db.Integer, db.ForeignKey("users.id"), nullable=False, index=True)
|
||||
share_token = db.Column(db.String(64), unique=True, nullable=False, index=True)
|
||||
is_private = db.Column(db.Boolean, nullable=False, default=True)
|
||||
password_hash = db.Column(db.String(256), nullable=True)
|
||||
created_at = db.Column(
|
||||
db.DateTime,
|
||||
nullable=False,
|
||||
default=lambda: datetime.now(timezone.utc),
|
||||
)
|
||||
|
||||
photos = db.relationship("Photo", backref="folder", lazy="dynamic")
|
||||
members = db.relationship("FolderMember", backref="folder", lazy="dynamic", cascade="all, delete-orphan")
|
||||
invites = db.relationship("FolderInvite", backref="folder", lazy="dynamic", cascade="all, delete-orphan")
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
if not self.share_token:
|
||||
self.share_token = uuid.uuid4().hex
|
||||
|
||||
def set_access_password(self, password):
|
||||
if password:
|
||||
self.password_hash = generate_password_hash(password)
|
||||
else:
|
||||
self.password_hash = None
|
||||
|
||||
def check_access_password(self, password):
|
||||
if not self.password_hash:
|
||||
return True
|
||||
return check_password_hash(self.password_hash, password)
|
||||
|
||||
@property
|
||||
def has_password(self):
|
||||
return bool(self.password_hash)
|
||||
|
||||
@property
|
||||
def photo_count(self):
|
||||
return self.photos.count()
|
||||
|
||||
def regenerate_share_token(self):
|
||||
self.share_token = uuid.uuid4().hex
|
||||
|
||||
|
||||
class FolderMember(db.Model):
|
||||
__tablename__ = "folder_members"
|
||||
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
folder_id = db.Column(db.Integer, db.ForeignKey("folders.id"), nullable=False, index=True)
|
||||
user_id = db.Column(db.Integer, db.ForeignKey("users.id"), nullable=False, index=True)
|
||||
role = db.Column(db.String(20), nullable=False, default="viewer")
|
||||
added_at = db.Column(
|
||||
db.DateTime,
|
||||
nullable=False,
|
||||
default=lambda: datetime.now(timezone.utc),
|
||||
)
|
||||
added_by_id = db.Column(db.Integer, db.ForeignKey("users.id"), nullable=True)
|
||||
|
||||
user = db.relationship("User", foreign_keys=[user_id])
|
||||
added_by = db.relationship("User", foreign_keys=[added_by_id])
|
||||
|
||||
__table_args__ = (db.UniqueConstraint("folder_id", "user_id", name="uq_folder_member"),)
|
||||
|
||||
|
||||
class FolderInvite(db.Model):
|
||||
__tablename__ = "folder_invites"
|
||||
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
folder_id = db.Column(db.Integer, db.ForeignKey("folders.id"), nullable=False, index=True)
|
||||
email = db.Column(db.String(120), nullable=False, index=True)
|
||||
role = db.Column(db.String(20), nullable=False, default="viewer")
|
||||
invited_by_id = db.Column(db.Integer, db.ForeignKey("users.id"), nullable=False)
|
||||
created_at = db.Column(
|
||||
db.DateTime,
|
||||
nullable=False,
|
||||
default=lambda: datetime.now(timezone.utc),
|
||||
)
|
||||
|
||||
invited_by = db.relationship("User", foreign_keys=[invited_by_id])
|
||||
|
||||
__table_args__ = (db.UniqueConstraint("folder_id", "email", name="uq_folder_invite"),)
|
||||
|
||||
|
||||
class Photo(db.Model):
|
||||
__tablename__ = "photos"
|
||||
|
||||
@@ -52,6 +140,7 @@ class Photo(db.Model):
|
||||
file_size = db.Column(db.Integer, nullable=False, default=0)
|
||||
mime_type = db.Column(db.String(100), nullable=False, default="image/jpeg")
|
||||
user_id = db.Column(db.Integer, db.ForeignKey("users.id"), nullable=True, index=True)
|
||||
folder_id = db.Column(db.Integer, db.ForeignKey("folders.id"), nullable=True, index=True)
|
||||
created_at = db.Column(
|
||||
db.DateTime,
|
||||
nullable=False,
|
||||
|
||||
Reference in New Issue
Block a user