package metadata import ( "context" "errors" "time" "git.lumeweb.com/LumeWeb/portal/db/models" "go.uber.org/fx" "gorm.io/gorm" ) var ErrNotFound = gorm.ErrRecordNotFound type UploadMetadata struct { UserID uint `json:"userId"` Hash []byte `json:"hash"` MimeType string `json:"mimeType"` Protocol string `json:"protocol"` UploaderIP string `json:"uploaderIp"` Size uint64 `json:"size"` Created time.Time `json:"created"` } func (u UploadMetadata) IsEmpty() bool { if u.UserID != 0 || u.MimeType != "" || u.Protocol != "" || u.UploaderIP != "" || u.Size != 0 { return false } if !u.Created.IsZero() { return false } if len(u.Hash) != 0 { return false } return true } var Module = fx.Module("metadata", fx.Provide( fx.Annotate( NewMetadataService, fx.As(new(MetadataService)), ), ), ) type MetadataService interface { SaveUpload(ctx context.Context, metadata UploadMetadata) error GetUpload(ctx context.Context, objectHash []byte) (UploadMetadata, error) DeleteUpload(ctx context.Context, objectHash []byte) error } type MetadataServiceDefault struct { db *gorm.DB } type MetadataServiceParams struct { fx.In Db *gorm.DB } func NewMetadataService(params MetadataServiceParams) *MetadataServiceDefault { return &MetadataServiceDefault{ db: params.Db, } } func (m *MetadataServiceDefault) SaveUpload(ctx context.Context, metadata UploadMetadata) error { var upload models.Upload upload.Hash = metadata.Hash ret := m.db.WithContext(ctx).Model(&models.Upload{}).Where(&upload).First(&upload) if ret.Error != nil { if errors.Is(ret.Error, gorm.ErrRecordNotFound) && ret.RowsAffected > 0 { return m.createUpload(ctx, metadata) } return ret.Error } changed := false if upload.UserID != metadata.UserID { changed = true } if upload.MimeType != metadata.MimeType { changed = true } if upload.Protocol != metadata.Protocol { changed = true } if upload.UploaderIP != metadata.UploaderIP { changed = true } if upload.Size != metadata.Size { changed = true } if changed { return m.db.Updates(&upload).Error } return nil } func (m *MetadataServiceDefault) createUpload(ctx context.Context, metadata UploadMetadata) error { upload := models.Upload{ UserID: metadata.UserID, Hash: metadata.Hash, MimeType: metadata.MimeType, Protocol: metadata.Protocol, UploaderIP: metadata.UploaderIP, Size: metadata.Size, } return m.db.WithContext(ctx).Create(&upload).Error } func (m *MetadataServiceDefault) GetUpload(ctx context.Context, objectHash []byte) (UploadMetadata, error) { var upload models.Upload upload.Hash = objectHash ret := m.db.WithContext(ctx).Model(&models.Upload{}).Where(&upload).First(&upload) if ret.Error != nil { if errors.Is(ret.Error, gorm.ErrRecordNotFound) { return UploadMetadata{}, ret.Error } } return UploadMetadata{ UserID: upload.UserID, Hash: upload.Hash, MimeType: upload.MimeType, Protocol: upload.Protocol, UploaderIP: upload.UploaderIP, Size: upload.Size, }, nil } func (m *MetadataServiceDefault) DeleteUpload(ctx context.Context, objectHash []byte) error { var upload models.Upload upload.Hash = objectHash ret := m.db.WithContext(ctx).Model(&models.Upload{}).Where(&upload).First(&upload) if ret.Error != nil { return ret.Error } return m.db.Delete(&upload).Error }