monorepo/cloud/maplefile-backend/internal/domain/collection/model.go

124 lines
7.1 KiB
Go

// monorepo/cloud/maplefile-backend/internal/maplefile/domain/collection/model.go
package collection
import (
"time"
"codeberg.org/mapleopentech/monorepo/cloud/maplefile-backend/internal/domain/crypto"
"codeberg.org/mapleopentech/monorepo/cloud/maplefile-backend/internal/domain/tag"
"github.com/gocql/gocql"
)
// Collection represents a folder or album.
// Can be used for both root collections and embedded subcollections
type Collection struct {
// Identifiers
// ID is the unique identifier for the collection in the cloud backend.
ID gocql.UUID `bson:"_id" json:"id"`
// OwnerID is the ID of the user who originally created and owns this collection.
// The owner has administrative privileges by default.
OwnerID gocql.UUID `bson:"owner_id" json:"owner_id"`
// Encryption and Content Details
// EncryptedName is the name of the collection, encrypted using the collection's unique key.
// Stored and transferred in encrypted form.
EncryptedName string `bson:"encrypted_name" json:"encrypted_name"`
// CollectionType indicates the nature of the collection, either "folder" or "album".
// Defined by CollectionTypeFolder and CollectionTypeAlbum constants.
CollectionType string `bson:"collection_type" json:"collection_type"` // "folder" or "album"
// EncryptedCollectionKey is the unique symmetric key used to encrypt the collection's data (like name and file metadata).
// This key is encrypted with the owner's master key for storage and transmission,
// allowing the owner's device to decrypt it using their master key.
EncryptedCollectionKey *crypto.EncryptedCollectionKey `bson:"encrypted_collection_key" json:"encrypted_collection_key"`
// EncryptedCustomIcon stores the custom icon for this collection, encrypted with the collection key.
// Empty string means use default folder/album icon.
// Contains either an emoji character (e.g., "📷") or "icon:<identifier>" for predefined icons.
EncryptedCustomIcon string `bson:"encrypted_custom_icon" json:"encrypted_custom_icon"`
// Sharing
// Collection members (users with access)
Members []CollectionMembership `bson:"members" json:"members"`
// Hierarchical structure fields
// ParentID is the ID of the parent collection if this is a subcollection.
// It is omitted (nil) for root collections. Used to reconstruct the hierarchy.
ParentID gocql.UUID `bson:"parent_id,omitempty" json:"parent_id,omitempty"` // Parent collection ID, not stored for root collections
// AncestorIDs is an array containing the IDs of all parent collections up to the root.
// This field is used for efficient querying and traversal of the collection hierarchy without joins.
AncestorIDs []gocql.UUID `bson:"ancestor_ids,omitempty" json:"ancestor_ids,omitempty"` // Array of ancestor IDs for efficient querying
// File count for performance optimization
// FileCount stores the number of active files in this collection.
// This denormalized field eliminates N+1 queries when listing collections.
FileCount int64 `bson:"file_count" json:"file_count"`
// DEPRECATED: Replaced by Tags field below
// TagIDs []gocql.UUID `bson:"tag_ids,omitempty" json:"tag_ids,omitempty"`
// Tags stores full embedded tag data (eliminates frontend API lookups)
// Stored as JSON text in database, marshaled/unmarshaled automatically
Tags []tag.EmbeddedTag `bson:"tags,omitempty" json:"tags,omitempty"`
// Ownership, timestamps and conflict resolution
// CreatedAt is the timestamp when the collection was initially created.
// Recorded on the local device and synced.
CreatedAt time.Time `bson:"created_at" json:"created_at"`
// CreatedByUserID is the ID of the user who created this file.
CreatedByUserID gocql.UUID `bson:"created_by_user_id" json:"created_by_user_id"`
// ModifiedAt is the timestamp of the last modification to the collection's metadata or content.
// Updated on the local device and synced.
ModifiedAt time.Time `bson:"modified_at" json:"modified_at"`
ModifiedByUserID gocql.UUID `bson:"modified_by_user_id" json:"modified_by_user_id"`
// The current version of the file.
Version uint64 `bson:"version" json:"version"` // Every mutation (create, update, delete, etc) is a versioned operation, keep track of the version number with this variable
// State management
State string `bson:"state" json:"state"` // active, deleted, archived
TombstoneVersion uint64 `bson:"tombstone_version" json:"tombstone_version"` // The `version` number that this collection was deleted at.
TombstoneExpiry time.Time `bson:"tombstone_expiry" json:"tombstone_expiry"`
}
// CollectionMembership represents a user's access to a collection
type CollectionMembership struct {
ID gocql.UUID `bson:"_id" json:"id"`
CollectionID gocql.UUID `bson:"collection_id" json:"collection_id"` // ID of the collection (redundant but helpful for queries)
RecipientID gocql.UUID `bson:"recipient_id" json:"recipient_id"` // User receiving access
RecipientEmail string `bson:"recipient_email" json:"recipient_email"` // Email for display purposes
GrantedByID gocql.UUID `bson:"granted_by_id" json:"granted_by_id"` // User who shared the collection
// Collection key encrypted with recipient's public key using box_seal. This matches the box_seal format which doesn't need a separate nonce.
EncryptedCollectionKey []byte `bson:"encrypted_collection_key" json:"encrypted_collection_key"`
// Access details
PermissionLevel string `bson:"permission_level" json:"permission_level"`
CreatedAt time.Time `bson:"created_at" json:"created_at"`
// Sharing origin tracking
IsInherited bool `bson:"is_inherited" json:"is_inherited"` // Tracks whether access was granted directly or inherited from a parent
InheritedFromID gocql.UUID `bson:"inherited_from_id,omitempty" json:"inherited_from_id,omitempty"` // InheritedFromID identifies which parent collection granted this access
}
// CollectionSyncCursor represents cursor-based pagination for sync operations
type CollectionSyncCursor struct {
LastModified time.Time `json:"last_modified" bson:"last_modified"`
LastID gocql.UUID `json:"last_id" bson:"last_id"`
}
// CollectionSyncItem represents minimal collection data for sync operations
type CollectionSyncItem struct {
ID gocql.UUID `json:"id" bson:"_id"`
Version uint64 `json:"version" bson:"version"`
ModifiedAt time.Time `json:"modified_at" bson:"modified_at"`
State string `json:"state" bson:"state"`
ParentID *gocql.UUID `json:"parent_id,omitempty" bson:"parent_id,omitempty"`
TombstoneVersion uint64 `bson:"tombstone_version" json:"tombstone_version"`
TombstoneExpiry time.Time `bson:"tombstone_expiry" json:"tombstone_expiry"`
EncryptedCustomIcon string `json:"encrypted_custom_icon,omitempty" bson:"encrypted_custom_icon,omitempty"`
}
// CollectionSyncResponse represents the response for collection sync data
type CollectionSyncResponse struct {
Collections []CollectionSyncItem `json:"collections"`
NextCursor *CollectionSyncCursor `json:"next_cursor,omitempty"`
HasMore bool `json:"has_more"`
}