portal/storage/storage.go

151 lines
3.1 KiB
Go
Raw Normal View History

2024-01-15 04:52:54 +00:00
package storage
import (
"bytes"
"encoding/hex"
"errors"
2024-01-15 04:52:54 +00:00
"git.lumeweb.com/LumeWeb/libs5-go/encoding"
2024-01-16 05:40:50 +00:00
"git.lumeweb.com/LumeWeb/portal/db/models"
2024-01-15 04:52:54 +00:00
"git.lumeweb.com/LumeWeb/portal/interfaces"
"github.com/go-resty/resty/v2"
"io"
"lukechampine.com/blake3"
)
var (
_ interfaces.StorageService = (*StorageServiceImpl)(nil)
)
type StorageServiceImpl struct {
portal interfaces.Portal
httpApi *resty.Client
}
func NewStorageService(portal interfaces.Portal) interfaces.StorageService {
return &StorageServiceImpl{
portal: portal,
httpApi: nil,
2024-01-15 04:52:54 +00:00
}
}
func (s StorageServiceImpl) PutFile(file io.ReadSeeker, bucket string, generateProof bool) ([]byte, error) {
2024-01-16 05:48:06 +00:00
hash, err := s.GetHash(file)
hashStr, err := encoding.NewMultihash(hash[:]).ToBase64Url()
2024-01-15 04:52:54 +00:00
if err != nil {
return nil, err
}
2024-01-16 05:48:06 +00:00
_, err = file.Seek(0, io.SeekStart)
2024-01-15 04:52:54 +00:00
if err != nil {
return nil, err
}
err = s.createBucketIfNotExists(bucket)
if err != nil {
return nil, err
}
2024-01-15 04:52:54 +00:00
resp, err := s.httpApi.R().
SetPathParam("path", hashStr).
SetFormData(map[string]string{
"bucket": bucket,
}).
2024-01-16 05:48:06 +00:00
SetBody(file).Put("/api/worker/objects/{path}")
2024-01-15 04:52:54 +00:00
if err != nil {
return nil, err
}
if resp.IsError() {
if resp.Error() != nil {
return nil, resp.Error().(error)
}
return nil, errors.New(resp.String())
2024-01-15 04:52:54 +00:00
}
return hash[:], nil
}
func (s *StorageServiceImpl) Init() {
client := resty.New()
2024-01-15 19:45:35 +00:00
client.SetDisableWarn(true)
client.SetBaseURL(s.portal.Config().GetString("core.sia.url"))
client.SetBasicAuth("", s.portal.Config().GetString("core.sia.key"))
s.httpApi = client
}
func (s *StorageServiceImpl) createBucketIfNotExists(bucket string) error {
resp, err := s.httpApi.R().
SetPathParam("bucket", bucket).
Get("/api/bus/bucket/{bucket}")
if err != nil {
return err
}
if resp.StatusCode() != 404 {
if resp.IsError() && resp.Error() != nil {
return resp.Error().(error)
}
} else {
resp, err := s.httpApi.R().
SetBody(map[string]string{
2024-01-15 19:36:06 +00:00
"name": bucket,
}).
2024-01-15 19:33:51 +00:00
Post("/api/bus/buckets")
if err != nil {
return err
}
if resp.IsError() && resp.Error() != nil {
return resp.Error().(error)
}
}
return nil
}
2024-01-16 05:40:50 +00:00
func (s *StorageServiceImpl) FileExists(hash []byte) (bool, models.Upload) {
hashStr := hex.EncodeToString(hash)
2024-01-16 05:40:50 +00:00
var upload models.Upload
2024-01-16 06:29:29 +00:00
result := s.portal.Database().Model(&models.Upload{}).Where(&models.Upload{Hash: hashStr}).First(&upload)
2024-01-16 05:40:50 +00:00
return result.RowsAffected > 0, upload
2024-01-16 05:40:50 +00:00
}
2024-01-16 05:48:06 +00:00
func (s *StorageServiceImpl) GetHash(file io.ReadSeeker) ([]byte, error) {
buf := bytes.NewBuffer(nil)
_, err := io.Copy(buf, file)
if err != nil {
return nil, err
}
2024-01-16 06:08:39 +00:00
hash := blake3.Sum256(buf.Bytes())
2024-01-16 05:48:06 +00:00
return hash[:], nil
}
2024-01-17 19:46:22 +00:00
func (s *StorageServiceImpl) CreateUpload(hash []byte, uploaderID uint, uploaderIP string, size uint64, protocol string) (*models.Upload, error) {
hashStr := hex.EncodeToString(hash)
upload := &models.Upload{
Hash: hashStr,
UserID: uploaderID,
UploaderIP: uploaderIP,
Protocol: protocol,
Size: size,
}
result := s.portal.Database().Create(upload)
if result.Error != nil {
return nil, result.Error
}
return upload, nil
}