mirror of
https://github.com/tdurieux/anonymous_github.git
synced 2026-11-14 00:07:00 +01:00
128 lines
3.2 KiB
Go
128 lines
3.2 KiB
Go
package server
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"path"
|
|
"strings"
|
|
|
|
"github.com/tdurieux/anonymous_github/backend/internal/anonymize"
|
|
"go.mongodb.org/mongo-driver/v2/bson"
|
|
"go.mongodb.org/mongo-driver/v2/mongo/options"
|
|
)
|
|
|
|
func folderQuery(raw string) (string, error) {
|
|
value := parseExtendedQuery(raw).object["path"]
|
|
if !value.truthy() {
|
|
return "", nil
|
|
}
|
|
requested, ok := value.scalarValue()
|
|
if !ok {
|
|
return "", errors.New("invalid_query_value")
|
|
}
|
|
return requested, nil
|
|
}
|
|
|
|
func (s *Server) originalFolder(ctx context.Context, repo M, requested string) (string, error) {
|
|
resolve := strings.Contains(requested, s.Config.Mask)
|
|
for _, term := range arr(obj(repo["options"])["terms"]) {
|
|
_, _, custom := anonymize.ParseTerm(str(term))
|
|
resolve = resolve || custom
|
|
}
|
|
if requested == "" || !resolve {
|
|
return requested, nil
|
|
}
|
|
filter := M{"repoId": repo["repoId"], "treeGeneration": activeGeneration(repo)}
|
|
directory, name := folderPathParts(requested)
|
|
filter["path"] = directory
|
|
if name != "" {
|
|
filter["name"] = name
|
|
}
|
|
exact, err := s.Store.one(ctx, "files", filter)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
if exact != nil {
|
|
if err := s.completeRecoveredMetadata(ctx, repo, exact); err != nil {
|
|
return "", err
|
|
}
|
|
return path.Join(str(exact["path"]), str(exact["name"])), nil
|
|
}
|
|
delete(filter, "path")
|
|
delete(filter, "name")
|
|
cursor, err := s.Store.DB.Collection("files").Find(ctx, filter, options.Find().SetSort(bson.D{{Key: "path", Value: 1}, {Key: "name", Value: 1}}).SetBatchSize(256).SetProjection(M{"path": 1, "name": 1, "metadataPending": 1, "recoverySnapshot": 1}))
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
defer cursor.Close(ctx)
|
|
engine, err := s.engine(repo, "repo")
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
for cursor.Next(ctx) {
|
|
var row M
|
|
if err := cursor.Decode(&row); err != nil {
|
|
return "", err
|
|
}
|
|
original := path.Join(str(row["path"]), str(row["name"]))
|
|
transformed, err := engine.Path(ctx, original)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
if transformed == requested {
|
|
if err := s.completeRecoveredMetadata(ctx, repo, row); err != nil {
|
|
return "", err
|
|
}
|
|
return original, nil
|
|
}
|
|
}
|
|
if err := cursor.Err(); err != nil {
|
|
return "", err
|
|
}
|
|
recovered, err := s.recoverTruncatedFile(ctx, repo, requested)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return path.Join(str(recovered["path"]), str(recovered["name"])), nil
|
|
}
|
|
|
|
// Match the POSIX dirname/basename operations used by AnonymizedFile before
|
|
// its exact Mongo lookup, including trailing and repeated separators.
|
|
func folderPathParts(requested string) (string, string) {
|
|
directory := "."
|
|
if len(requested) > 0 {
|
|
root := requested[0] == '/'
|
|
end := -1
|
|
trailing := true
|
|
for i := len(requested) - 1; i >= 1; i-- {
|
|
if requested[i] == '/' {
|
|
if !trailing {
|
|
end = i
|
|
break
|
|
}
|
|
} else {
|
|
trailing = false
|
|
}
|
|
}
|
|
if end < 0 {
|
|
if root {
|
|
directory = "/"
|
|
}
|
|
} else if root && end == 1 {
|
|
directory = "//"
|
|
} else {
|
|
directory = requested[:end]
|
|
}
|
|
}
|
|
if directory == "." {
|
|
directory = ""
|
|
}
|
|
directory = strings.TrimSuffix(directory, "/")
|
|
trimmed := strings.TrimRight(requested, "/")
|
|
name := trimmed
|
|
if i := strings.LastIndexByte(trimmed, '/'); i >= 0 {
|
|
name = trimmed[i+1:]
|
|
}
|
|
return directory, name
|
|
}
|