Files
PassKeeper/app/models/vault_item.py
T
nngo 0d7d9c1403
CI / Python lint (flake8) (push) Has been cancelled
CI / Python syntax check (push) Has been cancelled
CI / Alembic migration chain (push) Has been cancelled
CI / JavaScript syntax check (push) Has been cancelled
CI / Pytest (push) Has been cancelled
CI / Build extension zip (push) Has been cancelled
Aug 26 - Update password detect against off field 2
2026-08-26 15:05:48 -04:00

62 lines
2.7 KiB
Python

from datetime import datetime, timezone
import enum
from sqlalchemy.dialects.mysql import INTEGER
from app import db
class ItemType(str, enum.Enum):
PASSWORD = 'password'
NOTE = 'note'
ADDRESS = 'address'
CARD = 'card'
BANK = 'bank'
SSN = 'ssn'
PASSKEY = 'passkey'
class VaultItem(db.Model):
__tablename__ = 'vault_items'
id = db.Column(INTEGER(unsigned=True), autoincrement=True, primary_key=True)
user_id = db.Column(INTEGER(unsigned=True), db.ForeignKey('users.id', ondelete='CASCADE'), nullable=False)
folder_id = db.Column(INTEGER(unsigned=True), db.ForeignKey('folders.id', ondelete='SET NULL'), nullable=True)
item_type = db.Column(db.String(20), nullable=False, default=ItemType.PASSWORD.value)
# NOT the user-visible name — that lives encrypted in enc_name/iv_name below.
# This column holds the item TYPE string only (the same value as item_type),
# kept because the column is NOT NULL and predates enc_name. Writing a real
# item name here would hand the server plaintext the zero-knowledge model
# promises it never sees.
name = db.Column(db.String(255), nullable=False)
enc_data = db.Column(db.Text, nullable=False) # base64-encoded AES-256-GCM ciphertext
iv = db.Column(db.String(64), nullable=False) # base64-encoded 12-byte GCM nonce
# enc_name / iv_name: AES-256-GCM encrypted item name (client-side, same vault key).
# Nullable for backward-compatibility with existing rows — clients fall back to
# the plaintext 'name' column when enc_name is absent.
enc_name = db.Column(db.Text, nullable=True)
iv_name = db.Column(db.String(64), nullable=True)
created_at = db.Column(db.DateTime, default=lambda: datetime.now(timezone.utc).replace(tzinfo=None), nullable=False)
updated_at = db.Column(db.DateTime, default=lambda: datetime.now(timezone.utc).replace(tzinfo=None), onupdate=lambda: datetime.now(timezone.utc).replace(tzinfo=None), nullable=False)
def to_dict(self):
# item_type is stored as a plain string; handle both str and enum safely
item_type = self.item_type
if isinstance(item_type, ItemType):
item_type = item_type.value
return {
'id': self.id,
'item_type': item_type,
'name': self.name,
'folder_id': self.folder_id,
'enc_data': self.enc_data,
'iv': self.iv,
'enc_name': self.enc_name,
'iv_name': self.iv_name,
'created_at': self.created_at.isoformat() if self.created_at else None,
'updated_at': self.updated_at.isoformat() if self.updated_at else None,
}
def __repr__(self):
return f'<VaultItem {self.name}>'