[server] Version check support during ml data put (#5895)

## Description

## Tests
This commit is contained in:
Neeraj
2025-05-14 10:56:36 +05:30
committed by GitHub
4 changed files with 43 additions and 1 deletions

View File

@@ -26,6 +26,7 @@ type Entity struct {
Type ente.ObjectType `json:"type"`
EncryptedData string `json:"encryptedData"`
DecryptionHeader string `json:"decryptionHeader"`
UpdatedAt int64 `json:"updatedAt"`
}
type FDDiffRequest struct {

View File

@@ -11,6 +11,8 @@ type PutFileDataRequest struct {
EncryptedData *string `json:"encryptedData,omitempty"`
DecryptionHeader *string `json:"decryptionHeader,omitempty"`
Version *int `json:"version,omitempty"`
// Used to ensure that the client has correct state before it tries to update the metadata
LastUpdatedAt *int64 `json:"lastUpdatedAt,omitempty"`
}
func (r PutFileDataRequest) isEncDataPresent() bool {

View File

@@ -3,6 +3,7 @@ package filedata
import (
"context"
"errors"
"fmt"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/s3"
"github.com/aws/aws-sdk-go/service/s3/s3manager"
@@ -20,6 +21,7 @@ import (
"github.com/gin-contrib/requestid"
"github.com/gin-gonic/gin"
log "github.com/sirupsen/logrus"
"net/http"
"sync"
gTime "time"
)
@@ -95,6 +97,9 @@ func (c *Controller) InsertOrUpdateMetadata(ctx *gin.Context, req *fileData.PutF
if req.Type != ente.MlData {
return stacktrace.Propagate(ente.NewBadRequestWithMessage("unsupported object type "+string(req.Type)), "")
}
if versionErr := c._validateLastUpdatedAt(ctx, req.LastUpdatedAt, req.FileID, req.Type); versionErr != nil {
return stacktrace.Propagate(versionErr, "")
}
bucketID := c.S3Config.GetBucketID(req.Type)
objectKey := fileData.ObjectMetadataKey(req.FileID, fileOwnerID, req.Type, nil)
@@ -161,6 +166,7 @@ func (c *Controller) GetFileData(ctx *gin.Context, actorUser int64, req fileData
Type: doRows[0].Type,
EncryptedData: s3MetaObject.EncryptedData,
DecryptionHeader: s3MetaObject.DecryptionHeader,
UpdatedAt: doRows[0].UpdatedAt,
}, nil
}
@@ -205,6 +211,7 @@ func (c *Controller) GetFilesData(ctx *gin.Context, req fileData.GetFilesData) (
Type: obj.dbEntry.Type,
EncryptedData: obj.s3MetaObject.EncryptedData,
DecryptionHeader: obj.s3MetaObject.DecryptionHeader,
UpdatedAt: obj.dbEntry.UpdatedAt,
})
}
}
@@ -317,6 +324,38 @@ func (c *Controller) _checkMetadataReadOrWritePerm(ctx *gin.Context, userID int6
return nil
}
func (c *Controller) _validateLastUpdatedAt(ctx *gin.Context, lastUpdatedAt *int64, fileID int64, oType ente.ObjectType) error {
if lastUpdatedAt == nil {
return nil
}
doRows, err := c.Repo.GetFilesData(ctx, oType, []int64{fileID})
if err != nil {
return stacktrace.Propagate(err, "failed to get data")
}
var invalidVersionErr = &ente.ApiError{
HttpStatusCode: http.StatusConflict,
Code: "INVALID_VERSION",
Message: "",
}
if len(doRows) == 0 {
if *lastUpdatedAt == 0 {
return nil
}
invalidVersionErr.Message = "non zero version empty data"
return invalidVersionErr
}
if doRows[0].IsDeleted {
invalidVersionErr.Message = "data deleted"
return invalidVersionErr
}
dbUpdatedAt := doRows[0].UpdatedAt
if dbUpdatedAt != *lastUpdatedAt {
invalidVersionErr.Message = fmt.Sprintf("version mismatch expected %d, found %d", dbUpdatedAt, *lastUpdatedAt)
return invalidVersionErr
}
return nil
}
// _checkPreviewWritePerm is
func (c *Controller) _checkPreviewWritePerm(ctx *gin.Context, fileID int64, actorID int64) error {
err := c.AccessCtrl.VerifyFileOwnership(ctx, &access.VerifyFileOwnershipParams{

View File

@@ -13,8 +13,8 @@ import (
"github.com/ente-io/stacktrace"
"github.com/go-webauthn/webauthn/protocol"
"github.com/google/uuid"
"github.com/spf13/viper"
"github.com/sirupsen/logrus"
"github.com/spf13/viper"
"github.com/ente-io/museum/ente"
"github.com/ente-io/museum/pkg/utils/byteMarshaller"