Skip to content

Commit

Permalink
Merge pull request #134 from picosh/am/sshfs
Browse files Browse the repository at this point in the history
Added support for sshfs
  • Loading branch information
antoniomika authored May 30, 2024
2 parents 00dc4ec + bc64e0d commit 2e6c06e
Show file tree
Hide file tree
Showing 12 changed files with 245 additions and 96 deletions.
1 change: 1 addition & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
DATABASE_URL=postgresql://postgres:secret@postgres:5432/pico?sslmode=disable
POSTGRES_PASSWORD=secret
CF_API_TOKEN=secret
PICO_SECRET=secret
REGISTRY_URL=registry:5000
PICO_SECRET=""
PICO_SECRET_WEBHOOK=""
Expand Down
2 changes: 1 addition & 1 deletion db/postgres/storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -1553,7 +1553,7 @@ func (me *PsqlDB) FindFeedItemsByPostID(postID string) ([]*db.FeedItem, error) {

func (me *PsqlDB) InsertProject(userID, name, projectDir string) (string, error) {
if !shared.IsValidSubdomain(name) {
return "", fmt.Errorf("(%s) is not a valid project name, must match /^[a-z0-9-]+$/", name)
return "", fmt.Errorf("'%s' is not a valid project name, must match /^[a-z0-9-]+$/", name)
}

var id string
Expand Down
4 changes: 0 additions & 4 deletions feeds/cron.go
Original file line number Diff line number Diff line change
Expand Up @@ -218,10 +218,6 @@ func (f *Fetcher) ParseURL(fp *gofeed.Parser, url string) (*gofeed.Feed, error)
return nil, fmt.Errorf("fetching feed resulted in an error: %s %s", resp.Status, body)
}

if err != nil {
return nil, err
}

feed, err := fp.ParseString(string(body))

if err != nil {
Expand Down
134 changes: 103 additions & 31 deletions filehandlers/assets/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,12 @@ import (
"encoding/binary"
"fmt"
"io"
"io/fs"
"log/slog"
"os"
"path"
"path/filepath"
"slices"
"strings"
"time"

Expand Down Expand Up @@ -277,20 +280,16 @@ func (h *UploadAssetHandler) Write(s ssh.Session, entry *utils.FileEntry) (strin
h.Cfg.Logger.Error("user not found in ctx", "err", err.Error())
return "", err
}

if entry.Mode.IsDir() && strings.Count(entry.Filepath, "/") == 1 {
entry.Filepath = strings.TrimPrefix(entry.Filepath, "/")
}

logger := h.GetLogger().With(
"user", user.Name,
"file", entry.Filepath,
)

var origText []byte
if b, err := io.ReadAll(entry.Reader); err == nil {
origText = b
}
fileSize := binary.Size(origText)
// TODO: hack for now until I figure out how to get correct
// filesize from sftp,scp,rsync
entry.Size = int64(fileSize)

bucket, err := getBucket(s)
if err != nil {
logger.Error("could not find bucket in ctx", "err", err.Error())
Expand Down Expand Up @@ -325,11 +324,31 @@ func (h *UploadAssetHandler) Write(s ssh.Session, entry *utils.FileEntry) (strin
setProject(s, project)
}

if entry.Mode.IsDir() {
_, err := h.Storage.PutObject(
bucket,
path.Join(shared.GetAssetFileName(entry), "._pico_keep_dir"),
utils.NopReaderAtCloser(bytes.NewReader([]byte{})),
entry,
)
return "", err
}

var origText []byte
if b, err := io.ReadAll(entry.Reader); err == nil {
origText = b
}
fileSize := binary.Size(origText)
// TODO: hack for now until I figure out how to get correct
// filesize from sftp,scp,rsync
entry.Size = int64(fileSize)

storageSize := getStorageSize(s)
featureFlag, err := futil.GetFeatureFlag(s)
if err != nil {
return "", err
}

// calculate the filsize difference between the same file already
// stored and the updated file being uploaded
assetFilename := shared.GetAssetFileName(entry)
Expand Down Expand Up @@ -389,6 +408,66 @@ func (h *UploadAssetHandler) Write(s ssh.Session, entry *utils.FileEntry) (strin
return str, nil
}

func (h *UploadAssetHandler) Delete(s ssh.Session, entry *utils.FileEntry) error {
user, err := futil.GetUser(s)
if err != nil {
h.Cfg.Logger.Error("user not found in ctx", "err", err.Error())
return err
}

if entry.Mode.IsDir() && strings.Count(entry.Filepath, "/") == 1 {
entry.Filepath = strings.TrimPrefix(entry.Filepath, "/")
}

assetFilepath := shared.GetAssetFileName(entry)

logger := h.GetLogger().With(
"user", user.Name,
"file", assetFilepath,
)

bucket, err := getBucket(s)
if err != nil {
logger.Error("could not find bucket in ctx", "err", err.Error())
return err
}

projectName := shared.GetProjectName(entry)
logger = logger.With("project", projectName)

if assetFilepath == filepath.Join("/", projectName, "._pico_keep_dir") {
return os.ErrPermission
}

logger.Info("deleting file")

pathDir := filepath.Dir(assetFilepath)
fileName := filepath.Base(assetFilepath)

sibs, err := h.Storage.ListObjects(bucket, pathDir+"/", false)
if err != nil {
return err
}

sibs = slices.DeleteFunc(sibs, func(sib fs.FileInfo) bool {
return sib.Name() == fileName
})

if len(sibs) == 0 {
_, err := h.Storage.PutObject(
bucket,
filepath.Join(pathDir, "._pico_keep_dir"),
utils.NopReaderAtCloser(bytes.NewReader([]byte{})),
entry,
)
if err != nil {
return err
}
}

return h.Storage.DeleteObject(bucket, assetFilepath)
}

func (h *UploadAssetHandler) validateAsset(data *FileData) (bool, error) {
storageMax := data.FeatureFlag.Data.StorageMax
var nextStorageSize uint64
Expand Down Expand Up @@ -447,30 +526,23 @@ func (h *UploadAssetHandler) validateAsset(data *FileData) (bool, error) {
func (h *UploadAssetHandler) writeAsset(data *FileData) error {
assetFilepath := shared.GetAssetFileName(data.FileEntry)

if data.Size == 0 {
err := h.Storage.DeleteObject(data.Bucket, assetFilepath)
if err != nil {
return err
}
} else {
reader := bytes.NewReader(data.Text)
reader := bytes.NewReader(data.Text)

h.Cfg.Logger.Info(
"uploading file to bucket",
"user", data.User.Name,
"bucket", data.Bucket.Name,
"filename", assetFilepath,
)
h.Cfg.Logger.Info(
"uploading file to bucket",
"user", data.User.Name,
"bucket", data.Bucket.Name,
"filename", assetFilepath,
)

_, err := h.Storage.PutObject(
data.Bucket,
assetFilepath,
utils.NopReaderAtCloser(reader),
data.FileEntry,
)
if err != nil {
return err
}
_, err := h.Storage.PutObject(
data.Bucket,
assetFilepath,
utils.NopReaderAtCloser(reader),
data.FileEntry,
)
if err != nil {
return err
}

return nil
Expand Down
61 changes: 44 additions & 17 deletions filehandlers/imgs/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,23 +47,6 @@ func NewUploadImgHandler(dbpool db.DB, cfg *shared.ConfigSite, storage storage.S
}
}

func (h *UploadImgHandler) removePost(data *PostMetaData) error {
// skip empty files from being added to db
if data.Post == nil {
h.Cfg.Logger.Info("file is empty, skipping record", "filename", data.Filename)
return nil
}

h.Cfg.Logger.Info("file is empty, removing record", "filename", data.Filename, "recordId", data.Cur.ID)
err := h.DBPool.RemovePosts([]string{data.Cur.ID})
if err != nil {
h.Cfg.Logger.Error(err.Error(), "filename", data.Filename)
return fmt.Errorf("error for %s: %v", data.Filename, err)
}

return nil
}

func (h *UploadImgHandler) Read(s ssh.Session, entry *utils.FileEntry) (os.FileInfo, utils.ReaderAtCloser, error) {
user, err := util.GetUser(s)
if err != nil {
Expand Down Expand Up @@ -205,3 +188,47 @@ func (h *UploadImgHandler) Write(s ssh.Session, entry *utils.FileEntry) (string,
)
return str, nil
}

func (h *UploadImgHandler) Delete(s ssh.Session, entry *utils.FileEntry) error {
user, err := util.GetUser(s)
if err != nil {
return err
}

filename := filepath.Base(entry.Filepath)

logger := h.Cfg.Logger.With(
"user", user.Name,
"filename", filename,
)

post, err := h.DBPool.FindPostWithFilename(
filename,
user.ID,
Space,
)
if err != nil {
logger.Info("unable to find image, continuing", "err", err.Error())
return err
}

err = h.DBPool.RemovePosts([]string{post.ID})
if err != nil {
logger.Error("error removing image", "error", err)
return fmt.Errorf("error for %s: %v", filename, err)
}

bucket, err := h.Storage.UpsertBucket(user.ID)
if err != nil {
return err
}

err = h.Storage.DeleteObject(bucket, filename)
if err != nil {
return err
}

logger.Info("deleting image")

return nil
}
23 changes: 7 additions & 16 deletions filehandlers/imgs/img.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,27 +91,18 @@ func (h *UploadImgHandler) writeImg(s ssh.Session, data *PostMetaData) error {
return err
}

modTime := time.Unix(data.Mtime, 0)
modTime := time.Now()

if data.Mtime > 0 {
modTime = time.Unix(data.Mtime, 0)
}

logger := h.Cfg.Logger.With(
"user", data.Username,
"filename", data.Filename,
)

if len(data.OrigText) == 0 {
err = h.removePost(data)
if err != nil {
return err
}

bucket, err := h.Storage.UpsertBucket(data.User.ID)
if err != nil {
return err
}
err = h.Storage.DeleteObject(bucket, data.Filename)
if err != nil {
return err
}
} else if data.Cur == nil {
if data.Cur == nil {
logger.Info("file not found, adding record")
insertPost := db.Post{
UserID: user.ID,
Expand Down
58 changes: 43 additions & 15 deletions filehandlers/post_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,10 @@ func (h *ScpUploadHandler) Write(s ssh.Session, entry *utils.FileEntry) (string,
"filename", filename,
)

if entry.Mode.IsDir() {
return "", fmt.Errorf("file entry is directory, but only files are supported: %s", filename)
}

var origText []byte
if b, err := io.ReadAll(entry.Reader); err == nil {
origText = b
Expand Down Expand Up @@ -144,23 +148,14 @@ func (h *ScpUploadHandler) Write(s ssh.Session, entry *utils.FileEntry) (string,
return "", err
}

modTime := time.Unix(entry.Mtime, 0)
modTime := time.Now()

// if the file is empty we remove it from our database
if len(origText) == 0 {
// skip empty files from being added to db
if post == nil {
logger.Info("file is empty, skipping record")
return "", nil
}
if entry.Mtime > 0 {
modTime = time.Unix(entry.Mtime, 0)
}

err := h.DBPool.RemovePosts([]string{post.ID})
logger.Info("file is empty, removing record")
if err != nil {
logger.Error(err.Error())
return "", fmt.Errorf("error for %s: %v", filename, err)
}
} else if post == nil {
// if the file is empty we remove it from our database
if post == nil {
logger.Info("file not found, adding record")
insertPost := db.Post{
UserID: userID,
Expand Down Expand Up @@ -264,3 +259,36 @@ func (h *ScpUploadHandler) Write(s ssh.Session, entry *utils.FileEntry) (string,
curl := shared.NewCreateURL(h.Cfg)
return h.Cfg.FullPostURL(curl, user.Name, metadata.Slug), nil
}

func (h *ScpUploadHandler) Delete(s ssh.Session, entry *utils.FileEntry) error {
logger := h.Cfg.Logger
user, err := util.GetUser(s)
if err != nil {
logger.Error(err.Error())
return err
}

userID := user.ID
filename := filepath.Base(entry.Filepath)
logger = logger.With(
"user", user.Name,
"filename", filename,
)

post, err := h.DBPool.FindPostWithFilename(filename, userID, h.Cfg.Space)
if err != nil {
return err
}

if post == nil {
return os.ErrNotExist
}

err = h.DBPool.RemovePosts([]string{post.ID})
logger.Info("removing record")
if err != nil {
logger.Error(err.Error())
return fmt.Errorf("error for %s: %v", filename, err)
}
return nil
}
Loading

0 comments on commit 2e6c06e

Please sign in to comment.