MCPcopy Create free account
hub / github.com/bcspragu/logseq-sync / updateFiles

Method updateFiles

cmd/server/main.go:836–898  ·  view source on GitHub ↗
(ctx context.Context, req *updateFilesRequest)

Source from the content-addressed store, hash-verified

834}
835
836func (s *server) updateFiles(ctx context.Context, req *updateFilesRequest) (*updateFilesResponse, error) {
837 // Theoretically, the flow here is something like:
838 // 1. User calls getTempCredentials and gets
839 // 2. User PUTs some arbitrary number files to that location
840 // - This seems like an attack vector, but a short expiration should mitigate?
841 // 3. User calls this endpoint, noting the files they uploaded (at random names) and their checksums
842 // 4. Server (us! right here!) moves those files into their permanent locations
843
844 gID := db.GraphID(req.GraphUUID)
845
846 dbTxID, err := s.db.Tx(ctx, gID)
847 if err != nil {
848 return nil, httperr.Internal("failed to load TX: %w", err)
849 }
850
851 // This doesn't seem to actually be a part of the API, so it might be fine to
852 // omit, but the real API does namespace things by user ID.
853 userID, err := s.getUserID(ctx)
854 if err != nil {
855 return nil, httperr.Unauthorized("failed to load user ID: %w", err)
856 }
857 var successFiles []string
858 for id, tup := range req.Files {
859 srcPath, checksumStr := tup[0], tup[1]
860 checksum, err := hex.DecodeString(checksumStr)
861 if err != nil {
862 return nil, httperr.BadRequest("checksum %q wasn't hex-encoded", checksumStr)
863 }
864 if n := len(checksum); n != 16 {
865 return nil, httperr.BadRequest("checksum was %d bytes, expected 16 bytes", n)
866 }
867 dstPath := path.Join(string(userID), req.GraphUUID, id)
868 moveMeta, err := s.blob.Move(ctx, srcPath, dstPath)
869 if err != nil {
870 return nil, httperr.Internal("failed to move temp file: %w", err)
871 }
872 if err := s.db.SetFileMeta(ctx, gID, &db.FileMeta{
873 ID: db.FileID(id),
874 BlobPath: path.Join(s.blob.Bucket(), dstPath),
875 Checksum: checksum,
876 Size: moveMeta.Size,
877 LastModifiedAt: moveMeta.LastModified,
878 // TODO: Figure out transactions more generally, the pattern wasn't obvious to me.
879 LastModifiedTX: db.Tx(req.Txid),
880 }); err != nil {
881 return nil, httperr.Internal("failed to record file: %w", err)
882 }
883 successFiles = append(successFiles, dstPath)
884 }
885
886 curTX := max(req.Txid, int64(dbTxID)) + 1
887 if err := s.db.SetTx(ctx, gID, db.Tx(curTX)); err != nil {
888 return nil, httperr.Internal("failed to update tx: %w", err)
889 }
890
891 return &updateFilesResponse{
892 TXId: curTX,
893 // NOTE: Not sure in what case we'd want to use this. I guess maybe to only

Callers

nothing calls this directly

Calls 12

getUserIDMethod · 0.95
GraphIDTypeAlias · 0.92
InternalFunction · 0.92
UnauthorizedFunction · 0.92
BadRequestFunction · 0.92
FileIDTypeAlias · 0.92
TxTypeAlias · 0.92
TxMethod · 0.65
MoveMethod · 0.65
SetFileMetaMethod · 0.65
BucketMethod · 0.65
SetTxMethod · 0.65

Tested by

no test coverage detected