personal-website/webfilesystem/webfilesystem.go

198 lines
5.2 KiB
Go
Raw Normal View History

2023-03-22 21:53:06 +00:00
package webfilesystem
2023-04-25 09:37:42 +00:00
import (
"context"
2023-05-07 00:14:30 +00:00
"errors"
2023-04-25 09:37:42 +00:00
"strings"
2023-04-29 10:17:25 +00:00
"go.mongodb.org/mongo-driver/bson"
2023-04-25 09:37:42 +00:00
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/mongo"
)
2023-04-12 17:04:25 +00:00
2023-03-22 21:53:06 +00:00
type WebFileSystem struct {
2023-04-25 09:37:42 +00:00
webfsCollection *mongo.Collection
2023-05-07 00:14:30 +00:00
webfsFilesTable *mongo.Collection
webfsFilesData *mongo.Collection
2023-05-05 18:32:41 +00:00
ctx context.Context
2023-04-25 09:37:42 +00:00
}
func NewWebFileSystem(mongoClient *mongo.Client, dBName string, fsCollectionName string) *WebFileSystem {
return &WebFileSystem{
webfsCollection: mongoClient.Database(dBName).Collection(fsCollectionName), // TODO Check collection is exist
2023-05-07 00:14:30 +00:00
webfsFilesTable: mongoClient.Database(dBName).Collection("webfs-table"), // TODO Check collection is exist, //FIXME
webfsFilesData: mongoClient.Database(dBName).Collection("webfs-data"), // TODO Check collection is exist, //FIXME
2023-05-05 14:44:03 +00:00
ctx: context.Background(),
2023-04-25 09:37:42 +00:00
}
2023-03-22 21:53:06 +00:00
}
2023-05-07 01:00:22 +00:00
type FileHeader struct {
MongoId primitive.ObjectID `bson:"_id" json:"-"`
Name string `bson:"name" json:"name"`
Type string `bson:"type" json:"type"`
2023-05-07 20:20:16 +00:00
Icon string `bson:"icon" json:"icon"`
2023-05-07 21:20:40 +00:00
Data primitive.ObjectID `bson:"data_id" json:"-"` //TODO rename to DataId
2023-05-07 01:00:22 +00:00
}
2023-05-07 20:20:16 +00:00
func (fh *FileHeader) GetType() string {
//TODO return by extension and etc
return fh.Type
}
2023-05-07 01:00:22 +00:00
type BinaryFileData struct {
MongoId primitive.ObjectID `bson:"_id" json:"-"`
Bin []byte `bson:"bin" json:"-"`
}
2023-05-07 00:14:30 +00:00
// Deprecated
2023-05-07 01:00:22 +00:00
func (fs *WebFileSystem) ReadHeader(fileID primitive.ObjectID) (*FileHeader, error) {
file := &FileHeader{}
filter := primitive.M{
"_id": fileID,
}
err := fs.webfsFilesTable.FindOne(fs.ctx, filter).Decode(file)
2023-04-29 09:02:55 +00:00
return file, err
}
2023-05-07 01:00:22 +00:00
//TODO To private, get name from path and set it to file struct, force set newObjectID
func (fs *WebFileSystem) Write(filePath string, file *FileHeader, data interface{}) (primitive.ObjectID, primitive.ObjectID, error) {
headerId, dataId, err := fs.writeFileToMongo(file, data)
2023-04-29 09:02:55 +00:00
if err != nil {
2023-05-07 01:00:22 +00:00
return primitive.NilObjectID, primitive.NilObjectID, err
2023-04-29 09:02:55 +00:00
}
2023-05-07 01:00:22 +00:00
parentPath := fs.GetParentPath(filePath)
parentDir, err := fs.FindFile(parentPath)
if err != nil {
return primitive.NilObjectID, primitive.NilObjectID, err
}
if parentDir.IsZero() {
return primitive.NilObjectID, primitive.NilObjectID, errors.New("parent dir not found")
}
err = fs.AppendChildToDirectory(headerId, parentDir)
if err != nil {
return primitive.NilObjectID, primitive.NilObjectID, err
}
return headerId, dataId, nil
2023-04-29 09:02:55 +00:00
}
2023-05-07 01:00:22 +00:00
func (fs *WebFileSystem) UpdateFileData(file *FileHeader, data interface{}) error {
update := bson.M{"$set": data}
// println("updating data file: " + file.MongoId.String())
res, err := fs.webfsFilesData.UpdateByID(fs.ctx, file.Data, update)
if err != nil {
return err
}
if res.ModifiedCount < 1 {
return errors.New("no data updated")
}
return err
2023-04-29 10:17:25 +00:00
}
2023-05-07 01:00:22 +00:00
func (fs *WebFileSystem) InitFS() error { //FIXME Can't set parent_id to itself
rootData := DirectoryData{
MongoId: primitive.NewObjectID(),
Parent: primitive.NewObjectID(),
Children: []primitive.ObjectID{},
}
rootHeader := FileHeader{
MongoId: primitive.NewObjectID(),
Name: "/",
Type: "directory",
Icon: "",
2023-05-07 00:14:30 +00:00
}
2023-05-07 01:00:22 +00:00
_, _, err := fs.writeFileToMongo(&rootHeader, &rootData)
2023-04-29 10:17:25 +00:00
if err != nil {
return err
}
2023-05-07 01:00:22 +00:00
return nil
}
2023-05-07 00:14:30 +00:00
2023-05-07 01:00:22 +00:00
//TODO get on boot and safe to struct
func (fs *WebFileSystem) GetRootDir() (*FileHeader, *DirectoryData, error) {
filter := primitive.M{
"name": "/",
}
res := fs.webfsFilesTable.FindOne(fs.ctx, filter)
if res == nil {
return nil, nil, errors.New("TODO") //TODO
}
rootDir := FileHeader{}
err := res.Decode(&rootDir)
if res == nil {
return nil, nil, err
}
2023-05-07 00:14:30 +00:00
2023-05-07 01:00:22 +00:00
filterData := primitive.M{
"_id": rootDir.Data,
}
resData := fs.webfsFilesData.FindOne(fs.ctx, filterData)
if resData.Err() != nil {
return nil, nil, err
}
rootDirData := DirectoryData{}
err = resData.Decode(&rootDirData)
if err != nil {
return nil, nil, err
}
return &rootDir, &rootDirData, nil
}
func (fs *WebFileSystem) Remove(filePath string) error {
parentPath := fs.GetParentPath(filePath)
parentDirId, err := fs.FindFile(parentPath)
2023-04-29 09:02:55 +00:00
if err != nil {
return err
}
2023-05-07 01:00:22 +00:00
//TODO: Check, if parent file is dir
parentDirData := DirectoryData{}
parentDir, err := fs.readFSDocs(parentDirId, &parentDirData)
if err != nil {
return err
}
fileId, err := fs.FindFile(filePath)
if err != nil {
return err
}
newChildren := []primitive.ObjectID{}
for _, childId := range parentDirData.Children {
if childId != fileId {
newChildren = append(newChildren, childId)
}
}
parentDirData.Children = newChildren
err = fs.UpdateFileData(parentDir, parentDirData)
if err != nil {
return err
2023-05-07 00:14:30 +00:00
}
2023-04-29 09:02:55 +00:00
return nil
}
func (fs *WebFileSystem) SplitPath(path string) []string {
resPath := []string{}
splittedPath := strings.Split(path, "/")
splittedPath[0] = "/"
for _, split := range splittedPath {
if split != "" {
resPath = append(resPath, split)
}
}
return resPath
}
2023-05-02 00:12:43 +00:00
func (fs *WebFileSystem) GetExtension(filename string) string {
splittedName := strings.Split(filename, ".")
return splittedName[len(splittedName)-1]
}
2023-04-29 09:02:55 +00:00
func (fs *WebFileSystem) GetParentPath(path string) string {
splittedPath := fs.SplitPath(path)
2023-05-07 00:14:30 +00:00
if len(splittedPath) > 1 {
return "/" + strings.Join(splittedPath[1:len(splittedPath)-1], "/")
}
return "/"
2023-03-22 21:53:06 +00:00
}