Compare commits
4 Commits
main
...
meta_files
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7f8cadc022 | ||
|
|
e9970cf1f3 | ||
|
|
0ec6e2e0ae | ||
|
|
3442648826 |
@@ -480,6 +480,7 @@ func main() {
|
||||
privateAPI.GET("/files/data/preview", fileHandler.GetPreviewURL)
|
||||
|
||||
privateAPI.POST("/files", fileHandler.CreateOrUpdate)
|
||||
privateAPI.POST("/files/meta", fileHandler.CreateMetaFile)
|
||||
privateAPI.POST("/files/copy", fileHandler.CopyFiles)
|
||||
privateAPI.PUT("/files/update", fileHandler.Update)
|
||||
privateAPI.POST("/files/trash", fileHandler.Trash)
|
||||
|
||||
@@ -26,6 +26,20 @@ type File struct {
|
||||
Info *FileInfo `json:"info,omitempty"`
|
||||
}
|
||||
|
||||
type MetaFile struct {
|
||||
ID int64 `json:"id"`
|
||||
OwnerID int64 `json:"ownerID"`
|
||||
CollectionID int64 `json:"collectionID"`
|
||||
EncryptedKey string `json:"encryptedKey"`
|
||||
KeyDecryptionNonce string `json:"keyDecryptionNonce"`
|
||||
Metadata FileAttributes `json:"metadata" binding:"required"`
|
||||
// IsDeleted is True when the file ID is removed from the CollectionID
|
||||
IsDeleted bool `json:"isDeleted"`
|
||||
UpdationTime int64 `json:"updationTime"`
|
||||
MagicMetadata *MagicMetadata `json:"magicMetadata,omitempty"`
|
||||
PubicMagicMetadata *MagicMetadata `json:"pubMagicMetadata,omitempty"`
|
||||
}
|
||||
|
||||
// FileInfo has information about storage used by the file & it's metadata(future)
|
||||
type FileInfo struct {
|
||||
FileSize int64 `json:"fileSize,omitempty"`
|
||||
|
||||
@@ -2,14 +2,15 @@ package api
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/ente-io/museum/pkg/controller/file_copy"
|
||||
"github.com/ente-io/museum/pkg/controller/filedata"
|
||||
"github.com/ente-io/museum/pkg/controller/public"
|
||||
"net/http"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/ente-io/museum/pkg/controller/file_copy"
|
||||
"github.com/ente-io/museum/pkg/controller/filedata"
|
||||
"github.com/ente-io/museum/pkg/controller/public"
|
||||
|
||||
"github.com/ente-io/stacktrace"
|
||||
"github.com/gin-contrib/requestid"
|
||||
log "github.com/sirupsen/logrus"
|
||||
@@ -66,6 +67,32 @@ func (h *FileHandler) CreateOrUpdate(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, response)
|
||||
}
|
||||
|
||||
// CreateMetaFile creates an entry for a file
|
||||
func (h *FileHandler) CreateMetaFile(c *gin.Context) {
|
||||
userID := auth.GetUserID(c.Request.Header)
|
||||
var file ente.MetaFile
|
||||
if err := c.ShouldBindJSON(&file); err != nil {
|
||||
handler.Error(c, stacktrace.Propagate(err, ""))
|
||||
return
|
||||
}
|
||||
if file.ID != 0 {
|
||||
handler.Error(c, stacktrace.Propagate(ente.ErrBadRequest, "fileID can't be set when creating a new file"))
|
||||
return
|
||||
}
|
||||
file.UpdationTime = time.Microseconds()
|
||||
|
||||
// get an ente.App from the ?app= query parameter with a default of photos
|
||||
enteApp := auth.GetApp(c)
|
||||
file.OwnerID = userID
|
||||
file.IsDeleted = false
|
||||
resp, err := h.Controller.CreateMetaFile(c, userID, file, c.Request.UserAgent(), enteApp)
|
||||
if err != nil {
|
||||
handler.Error(c, stacktrace.Propagate(err, ""))
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, resp)
|
||||
}
|
||||
|
||||
// CopyFiles copies files that are owned by another user
|
||||
func (h *FileHandler) CopyFiles(c *gin.Context) {
|
||||
var req ente.CopyFileSyncRequest
|
||||
|
||||
28
server/pkg/controller/file_meta.go
Normal file
28
server/pkg/controller/file_meta.go
Normal file
@@ -0,0 +1,28 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"github.com/ente-io/museum/ente"
|
||||
"github.com/ente-io/stacktrace"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// CreateMetaFile adds an entry for a file in the respective tables
|
||||
func (c *FileController) CreateMetaFile(ctx *gin.Context, userID int64, file ente.MetaFile, userAgent string, app ente.App) (*ente.File, error) {
|
||||
collection, collErr := c.CollectionRepo.Get(file.CollectionID)
|
||||
if collErr != nil {
|
||||
return nil, stacktrace.Propagate(collErr, "")
|
||||
}
|
||||
// Verify that user owns the collection.
|
||||
// Warning: Do not remove this check
|
||||
if collection.Owner.ID != userID {
|
||||
return nil, stacktrace.Propagate(ente.ErrPermissionDenied, "collection doesn't belong to user")
|
||||
}
|
||||
if collection.IsDeleted {
|
||||
return nil, stacktrace.Propagate(ente.ErrCollectionDeleted, "collection has been deleted")
|
||||
}
|
||||
if file.OwnerID != userID {
|
||||
return nil, stacktrace.Propagate(ente.ErrPermissionDenied, "file ownerID doesn't match with userID")
|
||||
}
|
||||
resp, err := c.FileRepo.CreateMetaFile(file, userID, app)
|
||||
return resp, stacktrace.Propagate(err, "failed to create meta file")
|
||||
}
|
||||
@@ -126,6 +126,73 @@ func (repo *FileRepository) Create(
|
||||
return file, usage, stacktrace.Propagate(err, "")
|
||||
}
|
||||
|
||||
// CreateMetaFile creates an entry in the database for the given file
|
||||
func (repo *FileRepository) CreateMetaFile(
|
||||
metaFile ente.MetaFile,
|
||||
collectionOwnerID int64,
|
||||
app ente.App,
|
||||
) (*ente.File, error) {
|
||||
ctx := context.Background()
|
||||
tx, err := repo.DB.BeginTx(ctx, nil)
|
||||
if err != nil {
|
||||
return nil, stacktrace.Propagate(err, "")
|
||||
}
|
||||
if metaFile.OwnerID != collectionOwnerID {
|
||||
return nil, stacktrace.Propagate(errors.New("both file and collection should belong to same owner"), "")
|
||||
}
|
||||
|
||||
var fileID int64
|
||||
info := &ente.FileInfo{
|
||||
FileSize: 0,
|
||||
ThumbnailSize: 0,
|
||||
}
|
||||
err = tx.QueryRowContext(ctx, `INSERT INTO files
|
||||
(owner_id, encrypted_metadata,
|
||||
file_decryption_header, thumbnail_decryption_header, metadata_decryption_header,
|
||||
magic_metadata, pub_magic_metadata, info, updation_time)
|
||||
VALUES($1, $2, $3, $4, $5, $6, $7, $8, $9) RETURNING file_id`,
|
||||
metaFile.OwnerID, metaFile.Metadata.EncryptedData, "",
|
||||
"", metaFile.Metadata.DecryptionHeader,
|
||||
metaFile.MagicMetadata, metaFile.PubicMagicMetadata, info,
|
||||
metaFile.UpdationTime).Scan(&fileID)
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return nil, stacktrace.Propagate(err, "")
|
||||
}
|
||||
|
||||
_, err = tx.ExecContext(ctx, `INSERT INTO collection_files
|
||||
(collection_id, file_id, encrypted_key, key_decryption_nonce, is_deleted, updation_time, c_owner_id, f_owner_id)
|
||||
VALUES($1, $2, $3, $4, $5, $6, $7, $8)`, metaFile.CollectionID, metaFile.ID,
|
||||
metaFile.EncryptedKey, metaFile.KeyDecryptionNonce, false, metaFile.UpdationTime, metaFile.OwnerID, collectionOwnerID)
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return nil, stacktrace.Propagate(err, "")
|
||||
}
|
||||
_, err = tx.ExecContext(ctx, `UPDATE collections SET updation_time = $1
|
||||
WHERE collection_id = $2`, metaFile.UpdationTime, metaFile.CollectionID)
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return nil, stacktrace.Propagate(err, "")
|
||||
}
|
||||
err = tx.Commit()
|
||||
if err != nil {
|
||||
return nil, stacktrace.Propagate(err, "")
|
||||
}
|
||||
var file ente.File = ente.File{
|
||||
ID: fileID,
|
||||
UpdationTime: metaFile.UpdationTime,
|
||||
OwnerID: metaFile.OwnerID,
|
||||
Metadata: metaFile.Metadata,
|
||||
PubicMagicMetadata: metaFile.PubicMagicMetadata,
|
||||
MagicMetadata: metaFile.MagicMetadata,
|
||||
EncryptedKey: metaFile.EncryptedKey,
|
||||
KeyDecryptionNonce: metaFile.KeyDecryptionNonce,
|
||||
Info: info,
|
||||
CollectionID: collectionOwnerID,
|
||||
}
|
||||
return &file, stacktrace.Propagate(err, "")
|
||||
}
|
||||
|
||||
// markAsNeedingReplication inserts new entries in object_copies, setting the
|
||||
// current hot DC as the source copy.
|
||||
//
|
||||
|
||||
Reference in New Issue
Block a user