working on download container
parent
6be55038ea
commit
6f9c0c176d
2
Makefile
2
Makefile
|
@ -12,7 +12,7 @@ clean:
|
|||
rm -f db.sqlite
|
||||
|
||||
templ:
|
||||
rm -f web/template/*_templ.go
|
||||
rm -f web/templates/*_templ.go
|
||||
templ fmt .
|
||||
templ generate
|
||||
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
package db
|
||||
|
||||
// new creates a new and empty attachment
|
||||
func (attachment *Attachment) new() (*Attachment, error) {
|
||||
attachment = &Attachment{}
|
||||
if err := conn.Create(attachment).Error; err != nil {
|
||||
return attachment, err
|
||||
}
|
||||
return attachment, nil
|
||||
}
|
||||
|
||||
// save saves the (modified) Attachment
|
||||
func (attachment *Attachment) save() error {
|
||||
attachment = &Attachment{}
|
||||
if err := conn.Create(attachment).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
package db
|
||||
|
||||
// new creates a new and empty container
|
||||
func (container *Container) New() (*Container, error) {
|
||||
container = &Container{}
|
||||
if err := conn.Create(container).Error; err != nil {
|
||||
return container, err
|
||||
}
|
||||
return container, nil
|
||||
}
|
||||
|
||||
// save saves the (modified) container
|
||||
func (container *Container) Save() error {
|
||||
container = &Container{}
|
||||
if err := conn.Save(container).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// delete deltes the Container
|
||||
func (container *Container) Delete() error {
|
||||
container = &Container{}
|
||||
if err := conn.Delete(container).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
// ContainerByID gets the Container by its DB ID
|
||||
func ContainerByID(id uint) *Container {
|
||||
var container Container
|
||||
conn.First(&container, id)
|
||||
return &container
|
||||
}
|
||||
|
||||
// ContainerByFolder retrieves the Container by its folder UUID
|
||||
func ContainerByFolder(folder string) (*Container, error) {
|
||||
var container Container
|
||||
if err := conn.First(&container, folder).Error; err != nil {
|
||||
return &container, err
|
||||
}
|
||||
return &container, nil
|
||||
}
|
34
db/files.go
34
db/files.go
|
@ -6,6 +6,40 @@ import (
|
|||
"strconv"
|
||||
)
|
||||
|
||||
// newWithProperties Creates a new file with the given properties
|
||||
func (file *File) newWithProperties(name string, url string, comment string, blob string) (*File, error) {
|
||||
file = &File{
|
||||
Name: name,
|
||||
Comment: &comment,
|
||||
Blob: blob,
|
||||
Properties: FileProperties{
|
||||
Url: url,
|
||||
},
|
||||
}
|
||||
if err := conn.Create(file).Error; err != nil {
|
||||
return file, err
|
||||
|
||||
}
|
||||
|
||||
return file, nil
|
||||
}
|
||||
|
||||
// creates new empty file
|
||||
func (file *File) new() (*File,error) {
|
||||
if err := conn.Create(file).Error; err != nil {
|
||||
return file, err
|
||||
}
|
||||
return file, nil
|
||||
}
|
||||
|
||||
// save writes the given file to the Database
|
||||
func (file *File) save() error {
|
||||
if err := conn.Save(file).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func CreateFile(name string, url string, comment string, blob string) (uint, error) {
|
||||
file := File{
|
||||
Name: name,
|
||||
|
|
12
db/models.go
12
db/models.go
|
@ -72,3 +72,15 @@ type FileProperties struct {
|
|||
Extension string
|
||||
Url string
|
||||
}
|
||||
|
||||
type Container struct {
|
||||
gorm.Model
|
||||
ContainerID string
|
||||
FileID uint
|
||||
Status int
|
||||
Port int
|
||||
User string
|
||||
Password string //This has to be stored somewhere in plain text...
|
||||
ProxyFolder string
|
||||
Image string
|
||||
}
|
||||
|
|
|
@ -16,17 +16,17 @@ import (
|
|||
|
||||
// DownloadFile Downloads file from a given URL, stores it in a Minio object. This function also calls the Static
|
||||
// Analysis function
|
||||
func DownloadFile(rawURL string, blob string, id uint) error {
|
||||
func DownloadFile(rawURL string, blob string, id uint) (uint, error) {
|
||||
ctx := context.Background()
|
||||
fileURL, err := url.Parse(rawURL)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return err
|
||||
return 0, err
|
||||
}
|
||||
response, err := http.Get(rawURL)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return err
|
||||
return 0, err
|
||||
}
|
||||
defer func(Body io.ReadCloser) {
|
||||
err := Body.Close()
|
||||
|
@ -48,13 +48,13 @@ func DownloadFile(rawURL string, blob string, id uint) error {
|
|||
minio.PutObjectOptions{ContentType: contentType})
|
||||
if err != nil {
|
||||
log.Printf("Could not create File object: %v \n", err)
|
||||
return err
|
||||
return 0, err
|
||||
}
|
||||
log.Printf("Successfully uploaded %s of size %d\n", blob, objectInfo.Size)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return err
|
||||
return 0, err
|
||||
}
|
||||
go RunStaticAnalysis(id)
|
||||
return nil
|
||||
return 0, nil
|
||||
}
|
||||
|
|
|
@ -3,30 +3,39 @@ package files
|
|||
import (
|
||||
"context"
|
||||
"log"
|
||||
"mime/multipart"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/minio/minio-go/v7"
|
||||
"github.com/spf13/viper"
|
||||
"github.com/spf13/viper"
|
||||
"github.com/google/uuid"
|
||||
|
||||
"git.jmbit.de/filegate/filegate/db"
|
||||
)
|
||||
|
||||
func UploadFile(id uint, blob string, c *gin.Context) error {
|
||||
func UploadFile(file *multipart.FileHeader, name string, url string, comment string) (uint, error) {
|
||||
ctx := context.Background()
|
||||
file, err := c.FormFile("file")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
db.UpdateOriginalName(id, file.Filename)
|
||||
objectInfo, err := MinioClient.PutObject(ctx, viper.GetString("minio.bucket"), blob, c.Request.Body, c.Request.ContentLength,
|
||||
minio.PutObjectOptions{ContentType: c.ContentType()})
|
||||
blob := uuid.NewString()
|
||||
fileReader, err := file.Open()
|
||||
if err != nil {
|
||||
log.Printf("Could not create File object: %v \n", err)
|
||||
return err
|
||||
return 0, err
|
||||
}
|
||||
fileSize := file.Size
|
||||
fileID, err := db.CreateFile(name, url, comment, blob)
|
||||
if err != nil {
|
||||
log.Printf("Could not create File object: %v \n", err)
|
||||
return fileID, err
|
||||
}
|
||||
db.UpdateOriginalName(fileID, file.Filename)
|
||||
objectInfo, err := MinioClient.PutObject(ctx, viper.GetString("minio.bucket"), blob, fileReader, fileSize,
|
||||
minio.PutObjectOptions{ContentType: "application/octet-stream"})
|
||||
if err != nil {
|
||||
log.Printf("Could not create File object: %v \n", err)
|
||||
return fileID, err
|
||||
}
|
||||
log.Printf("Successfully uploaded %s of size %d\n", blob, objectInfo.Size)
|
||||
go RunStaticAnalysis(id)
|
||||
return nil
|
||||
go RunStaticAnalysis(fileID)
|
||||
return fileID, nil
|
||||
}
|
||||
|
||||
// GetFile returns a pointer to a File stored in Minio by passing it the UUID ("Blob"-ID) of the file
|
||||
|
|
|
@ -1,41 +1,116 @@
|
|||
package pods
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/containers/podman/v4/pkg/bindings/containers"
|
||||
"github.com/containers/podman/v4/pkg/bindings/images"
|
||||
"github.com/containers/podman/v4/pkg/specgen"
|
||||
"log"
|
||||
"github.com/google/uuid"
|
||||
|
||||
"git.jmbit.de/filegate/filegate/db"
|
||||
"git.jmbit.de/filegate/filegate/utils"
|
||||
)
|
||||
|
||||
func CreateDownloadContainer(user string, passwd string, folder string) string {
|
||||
// CreateDownloadContainer() creates Download Container and returns path UUID
|
||||
func CreateDownloadContainer() (string, error) {
|
||||
image := "docker.io/linuxserver/firefox:version-116.0-r0"
|
||||
user := "abc"
|
||||
folder := uuid.NewString()
|
||||
passwd, err := utils.RandomString(32)
|
||||
if err != nil {
|
||||
log.Printf("Error creating Download Container PW: %v", err)
|
||||
passwd = ""
|
||||
}
|
||||
|
||||
container, err := initializeDownloadContainer(user, passwd, folder, image)
|
||||
if err != nil {
|
||||
return container.ProxyFolder, err
|
||||
}
|
||||
container, err = startDownloadContainer(container)
|
||||
if err != nil {
|
||||
return container.ProxyFolder, err
|
||||
}
|
||||
err = registerDownloadContainer(container)
|
||||
|
||||
return container.ProxyFolder, err
|
||||
}
|
||||
|
||||
// DestroyDownloadContainer resolves the Container ID from its folder UUID and destroys it
|
||||
func DestroyDownloadContainer(folder string) {
|
||||
|
||||
}
|
||||
|
||||
// initializeDownloadContainer() creates the Container Struct
|
||||
func initializeDownloadContainer(
|
||||
user string,
|
||||
passwd string,
|
||||
folder string,
|
||||
image string,
|
||||
) (*db.Container, error) {
|
||||
container := &db.Container{
|
||||
User: user,
|
||||
Password: passwd,
|
||||
ProxyFolder: folder,
|
||||
Image: image,
|
||||
}
|
||||
container, err := container.New()
|
||||
if err != nil {
|
||||
log.Printf("Error initializing Download Container Object: %v", err)
|
||||
}
|
||||
return container, err
|
||||
}
|
||||
|
||||
// startDownloadContainer() takes a Container struct and creates the DownloadContainer for it
|
||||
func startDownloadContainer(container *db.Container) (*db.Container, error) {
|
||||
image := "docker.io/linuxserver/firefox:latest"
|
||||
conn := socketConnection()
|
||||
_, err := images.Pull(conn, image, nil)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
s := specgen.NewSpecGenerator(image, false)
|
||||
s.Env["CUSTOM_USER"] = user
|
||||
s.Env["PASSWORD"] = passwd
|
||||
s.Env["CUSTOM_USER"] = container.User
|
||||
s.Env["PASSWORD"] = container.Password
|
||||
s.Env["START_DOCKER"] = "False"
|
||||
s.Env["TITLE"] = "Filegate Download Browser"
|
||||
s.Env["SUBFOLDER"] = folder
|
||||
s.Env["PUID"] = "1000"
|
||||
s.Env["GUID"] = "1000"
|
||||
// Use the Containers ID as port offset
|
||||
// TODO: Use better networking to access Download Container
|
||||
s.Env["CUSTOM_PORT"] = fmt.Sprintf("%d", 3000+container.ID)
|
||||
s.Env["SUBFOLDER"] = fmt.Sprintf("/browser/%s/", container.ProxyFolder)
|
||||
createResponse, err := containers.CreateWithSpec(conn, s, nil)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return container, err
|
||||
}
|
||||
if err := containers.Start(conn, createResponse.ID, nil); err != nil {
|
||||
log.Println(err)
|
||||
return container, err
|
||||
}
|
||||
return createResponse.ID
|
||||
container.ContainerID = createResponse.ID
|
||||
return container, nil
|
||||
}
|
||||
|
||||
func DestroyDownloadContainer(id string) {
|
||||
conn := socketConnection()
|
||||
if err := containers.Kill(conn, id, nil); err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
if err, _ := containers.Remove(conn, id, nil); err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
// registerDownloadContainer() saves the Container to the Database
|
||||
func registerDownloadContainer(container *db.Container) error {
|
||||
err := container.Save()
|
||||
return err
|
||||
}
|
||||
|
||||
// removeDownloadContainer() removes the Container from Podman and the Database
|
||||
func removeDownloadContainer(container *db.Container) error {
|
||||
conn := socketConnection()
|
||||
if err := containers.Kill(conn, container.ContainerID, nil); err != nil {
|
||||
log.Println(err)
|
||||
return err
|
||||
}
|
||||
if _, err := containers.Remove(conn, container.ContainerID, nil); err != nil {
|
||||
log.Println(err)
|
||||
return err
|
||||
}
|
||||
container.Delete()
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package files
|
||||
package service
|
||||
|
||||
import (
|
||||
"crypto/md5"
|
||||
|
@ -14,6 +14,7 @@ import (
|
|||
"github.com/spf13/viper"
|
||||
|
||||
"git.jmbit.de/filegate/filegate/db"
|
||||
"git.jmbit.de/filegate/filegate/files"
|
||||
)
|
||||
|
||||
func mimeType(path string) string {
|
||||
|
@ -79,14 +80,19 @@ func fileSize(path string) int64 {
|
|||
func RunStaticAnalysis(id uint) {
|
||||
file := db.GetFileByID(id)
|
||||
|
||||
filepath := fmt.Sprintf("%s/%d/%s", viper.GetString("tempfiles"), file.ID, file.Properties.OriginalName)
|
||||
filepath := fmt.Sprintf(
|
||||
"%s/%d/%s",
|
||||
viper.GetString("tempfiles"),
|
||||
file.ID,
|
||||
file.Properties.OriginalName,
|
||||
)
|
||||
err := os.Mkdir(fmt.Sprintf("%s/%d", viper.GetString("tempfiles"), file.ID), 700)
|
||||
if err != nil {
|
||||
|
||||
log.Printf("Error Creating analysis directory, %v", err)
|
||||
return
|
||||
}
|
||||
fileObject, err := GetFile(file.Blob)
|
||||
fileObject, err := files.GetFile(file.Blob)
|
||||
if err != nil {
|
||||
log.Printf("Error getting file from S3, %v", err)
|
||||
fileObject.Close()
|
||||
|
@ -113,5 +119,14 @@ func RunStaticAnalysis(id uint) {
|
|||
fileSize := fileSize(filepath)
|
||||
md5Sum, sha1Sum, sha256Sum := fileChecksums(filepath)
|
||||
|
||||
db.SetSimpleAttributes(id, mimeType, fileSize, sha256Sum, sha1Sum, md5Sum, fileCmd, fileExtension)
|
||||
db.SetSimpleAttributes(
|
||||
id,
|
||||
mimeType,
|
||||
fileSize,
|
||||
sha256Sum,
|
||||
sha1Sum,
|
||||
md5Sum,
|
||||
fileCmd,
|
||||
fileExtension,
|
||||
)
|
||||
}
|
|
@ -9,13 +9,13 @@ import (
|
|||
|
||||
func reverseProxy(c *gin.Context, target string) {
|
||||
director := func(req *http.Request) {
|
||||
r := c.Request
|
||||
//r := c.Request
|
||||
|
||||
req.URL.Scheme = "http"
|
||||
req.URL.Host = target
|
||||
req.Header["my-header"] = []string{r.Header.Get("my-header")}
|
||||
// Golang camelcases headers
|
||||
delete(req.Header, "My-Header")
|
||||
//req.Header["my-header"] = []string{r.Header.Get("my-header")}
|
||||
//// Golang camelcases headers
|
||||
//delete(req.Header, "My-Header")
|
||||
}
|
||||
proxy := &httputil.ReverseProxy{Director: director}
|
||||
proxy.ServeHTTP(c.Writer, c.Request)
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
package templates
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
// Code generated by templ - DO NOT EDIT.
|
||||
|
||||
// templ: version: 0.2.476
|
||||
package templates
|
||||
|
||||
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
||||
|
||||
import "github.com/a-h/templ"
|
|
@ -0,0 +1,14 @@
|
|||
package ui
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.jmbit.de/filegate/filegate/utils"
|
||||
"git.jmbit.de/filegate/filegate/web/templates"
|
||||
)
|
||||
|
||||
func getBrowser(c *gin.Context) {
|
||||
c.HTML(http.StatusOK, "", templates.Index(utils.GenMetaContent(c), nil))
|
||||
}
|
|
@ -25,7 +25,7 @@ func postLogin(c *gin.Context) {
|
|||
metaContent := utils.GenMetaContent(c)
|
||||
metaContent.ErrorTitle = "Error"
|
||||
metaContent.ErrorText = err.Error()
|
||||
c.HTML(http.StatusUnauthorized, "", templates.Login(metaContent, "Login"))
|
||||
c.HTML(http.StatusUnauthorized, "", templates.Login(metaContent, "Login", err))
|
||||
log.Println(err)
|
||||
return
|
||||
} else {
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
package ui
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.jmbit.de/filegate/filegate/files"
|
||||
"git.jmbit.de/filegate/filegate/utils"
|
||||
"git.jmbit.de/filegate/filegate/web/templates"
|
||||
)
|
||||
|
@ -13,6 +16,62 @@ func getNewFile(c *gin.Context) {
|
|||
c.HTML(http.StatusOK, "", templates.NewFilePage(utils.GenMetaContent(c), "New File", nil))
|
||||
}
|
||||
|
||||
func postNewFile(c *gin.Context) {
|
||||
c.HTML(http.StatusOK, "", templates.NewFilePage(utils.GenMetaContent(c), "New File", nil))
|
||||
func postNewFileUpload(c *gin.Context) {
|
||||
name := c.PostForm("name")
|
||||
url := "N/A"
|
||||
comment := c.PostForm("comment")
|
||||
file, err := c.FormFile("file")
|
||||
if err != nil {
|
||||
newFileError(c, err)
|
||||
return
|
||||
}
|
||||
fileid, err := files.UploadFile(file, name, url, comment)
|
||||
if err != nil {
|
||||
newFileError(c, err)
|
||||
return
|
||||
}
|
||||
c.Redirect(http.StatusTemporaryRedirect, fmt.Sprintf("/file/%d", fileid))
|
||||
}
|
||||
|
||||
func postNewFileDownload(c *gin.Context) {
|
||||
name := c.PostForm("name")
|
||||
url := c.PostForm("url")
|
||||
comment := c.PostForm("comment")
|
||||
file, err := c.FormFile("file")
|
||||
if err != nil {
|
||||
newFileError(c, err)
|
||||
return
|
||||
}
|
||||
fileid, err := files.UploadFile(file, name, url, comment)
|
||||
if err != nil {
|
||||
newFileError(c, err)
|
||||
return
|
||||
}
|
||||
c.Redirect(http.StatusTemporaryRedirect, fmt.Sprintf("/file/%d", fileid))
|
||||
}
|
||||
|
||||
func postNewFileBrowser(c *gin.Context) {
|
||||
name := c.PostForm("name")
|
||||
url := c.PostForm("url")
|
||||
comment := c.PostForm("comment")
|
||||
file, err := c.FormFile("file")
|
||||
if err != nil {
|
||||
newFileError(c, err)
|
||||
return
|
||||
}
|
||||
fileid, err := files.UploadFile(file, name, url, comment)
|
||||
if err != nil {
|
||||
newFileError(c, err)
|
||||
return
|
||||
}
|
||||
c.Redirect(http.StatusTemporaryRedirect, fmt.Sprintf("/file/%d", fileid))
|
||||
}
|
||||
|
||||
func newFileError(c *gin.Context, err error) {
|
||||
metaContent := utils.GenMetaContent(c)
|
||||
metaContent.ErrorTitle = "Error"
|
||||
metaContent.ErrorText = err.Error()
|
||||
c.HTML(http.StatusOK, "", templates.NewFilePage(utils.GenMetaContent(c), "New File", err))
|
||||
log.Println(err)
|
||||
return
|
||||
}
|
||||
|
|
|
@ -10,9 +10,13 @@ func GroupWeb(router *gin.Engine) *gin.Engine {
|
|||
router.POST("/", index)
|
||||
router.GET("/login.html", getLogin)
|
||||
router.POST("/login.html", postLogin)
|
||||
router.GET("/file/", getFileListPage)
|
||||
router.GET("/file/new/", getNewFile)
|
||||
router.POST("/file/new/", postNewFile)
|
||||
file := router.Group("/file/")
|
||||
file.GET("/", getFileListPage)
|
||||
file.GET("/new/", getNewFile)
|
||||
file.POST("/new/upload", postNewFileUpload)
|
||||
file.POST("/new/download", postNewFileDownload)
|
||||
file.POST("/new/browser", postNewFileBrowser)
|
||||
router.GET("/browser/:id", getBrowser)
|
||||
|
||||
return router
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue