Fixed up the .gitignore
More push to move towards a deployment stage
This commit is contained in:
@@ -1,83 +1,95 @@
|
||||
package config
|
||||
package storage
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"io"
|
||||
"os"
|
||||
|
||||
"gopkg.in/yaml.v3"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
ShardID string `yaml:"shard_id"`
|
||||
Listen struct {
|
||||
HTTP string `yaml:"http"`
|
||||
HTTPS string `yaml:"https"`
|
||||
WS string `yaml:"ws"`
|
||||
} `yaml:"listen"`
|
||||
TLS struct {
|
||||
Enable bool `yaml:"enable"`
|
||||
CertFile string `yaml:"cert_file"`
|
||||
KeyFile string `yaml:"key_file"`
|
||||
} `yaml:"tls"`
|
||||
Federation struct {
|
||||
MTLSEnable bool `yaml:"mtls_enable"`
|
||||
Listen string `yaml:"listen"`
|
||||
CertFile string `yaml:"cert_file"`
|
||||
KeyFile string `yaml:"key_file"`
|
||||
ClientCAFile string `yaml:"client_ca_file"`
|
||||
} `yaml:"federation"`
|
||||
Storage struct {
|
||||
Backend string `yaml:"backend"`
|
||||
Path string `yaml:"path"`
|
||||
MaxObjectKB int `yaml:"max_object_kb"`
|
||||
} `yaml:"storage"`
|
||||
Security struct {
|
||||
ZeroTrust bool `yaml:"zero_trust"`
|
||||
RequireMTLSForFederation bool `yaml:"require_mtls_for_federation"`
|
||||
AcceptClientSignedTokens bool `yaml:"accept_client_signed_tokens"`
|
||||
LogLevel string `yaml:"log_level"`
|
||||
} `yaml:"security"`
|
||||
Privacy struct {
|
||||
RetainIP string `yaml:"retain_ip"`
|
||||
RetainUserAgent string `yaml:"retain_user_agent"`
|
||||
RetainTimestamps string `yaml:"retain_timestamps"`
|
||||
} `yaml:"privacy"`
|
||||
Auth struct {
|
||||
SigningSecret string `yaml:"signing_secret"`
|
||||
SSO struct {
|
||||
Discord struct {
|
||||
Enabled bool `yaml:"enabled"`
|
||||
ClientID string `yaml:"client_id"`
|
||||
ClientSecret string `yaml:"client_secret"`
|
||||
RedirectURI string `yaml:"redirect_uri"`
|
||||
} `yaml:"discord"`
|
||||
Google struct {
|
||||
Enabled bool `yaml:"enabled"`
|
||||
ClientID string `yaml:"client_id"`
|
||||
ClientSecret string `yaml:"client_secret"`
|
||||
RedirectURI string `yaml:"redirect_uri"`
|
||||
} `yaml:"google"`
|
||||
Facebook struct {
|
||||
Enabled bool `yaml:"enabled"`
|
||||
ClientID string `yaml:"client_id"`
|
||||
ClientSecret string `yaml:"client_secret"`
|
||||
RedirectURI string `yaml:"redirect_uri"`
|
||||
} `yaml:"facebook"`
|
||||
} `yaml:"sso"`
|
||||
TwoFactor struct {
|
||||
WebAuthnEnabled bool `yaml:"webauthn_enabled"`
|
||||
TOTPEnabled bool `yaml:"totp_enabled"`
|
||||
} `yaml:"two_factor"`
|
||||
} `yaml:"auth"`
|
||||
type FSStore struct {
|
||||
root string
|
||||
maxObjectB int64
|
||||
}
|
||||
|
||||
func Load(path string) (*Config, error) {
|
||||
b, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
func NewFSStore(root string, maxKB int) (*FSStore, error) {
|
||||
if root == "" {
|
||||
root = "./data/objects"
|
||||
}
|
||||
if err := os.MkdirAll(root, 0o755); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var c Config
|
||||
if err := yaml.Unmarshal(b, &c); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &c, nil
|
||||
return &FSStore{root: root, maxObjectB: int64(maxKB) * 1024}, nil
|
||||
}
|
||||
|
||||
func (s *FSStore) Put(r io.Reader) (string, int64, error) {
|
||||
h := sha256.New()
|
||||
tmp := filepath.Join(s.root, ".tmp")
|
||||
_ = os.MkdirAll(tmp, 0o755)
|
||||
f, err := os.CreateTemp(tmp, "obj-*")
|
||||
if err != nil {
|
||||
return "", 0, err
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
var n int64
|
||||
buf := make([]byte, 32*1024)
|
||||
for {
|
||||
m, er := r.Read(buf)
|
||||
if m > 0 {
|
||||
n += int64(m)
|
||||
if s.maxObjectB > 0 && n > s.maxObjectB {
|
||||
return "", 0, errors.New("object too large")
|
||||
}
|
||||
_, _ = h.Write(buf[:m])
|
||||
if _, werr := f.Write(buf[:m]); werr != nil {
|
||||
return "", 0, werr
|
||||
}
|
||||
}
|
||||
if er == io.EOF {
|
||||
break
|
||||
}
|
||||
if er != nil {
|
||||
return "", 0, er
|
||||
}
|
||||
}
|
||||
sum := hex.EncodeToString(h.Sum(nil))
|
||||
dst := filepath.Join(s.root, sum[:2], sum[2:4], sum)
|
||||
if err := os.MkdirAll(filepath.Dir(dst), 0o755); err != nil {
|
||||
return "", 0, err
|
||||
}
|
||||
if err := os.Rename(f.Name(), dst); err != nil {
|
||||
return "", 0, err
|
||||
}
|
||||
return sum, n, nil
|
||||
}
|
||||
|
||||
func (s *FSStore) pathFor(hash string) string {
|
||||
return filepath.Join(s.root, hash[:2], hash[2:4], hash)
|
||||
}
|
||||
|
||||
func (s *FSStore) Get(hash string) (string, error) {
|
||||
if len(hash) < 4 {
|
||||
return "", os.ErrNotExist
|
||||
}
|
||||
p := s.pathFor(hash)
|
||||
if _, err := os.Stat(p); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return p, nil
|
||||
}
|
||||
|
||||
func (s *FSStore) Delete(hash string) error {
|
||||
if len(hash) < 4 {
|
||||
return os.ErrNotExist
|
||||
}
|
||||
p := s.pathFor(hash)
|
||||
if err := os.Remove(p); err != nil {
|
||||
return err
|
||||
}
|
||||
_ = os.Remove(filepath.Dir(p))
|
||||
_ = os.Remove(filepath.Dir(filepath.Dir(p)))
|
||||
return nil
|
||||
}
|
||||
|
Reference in New Issue
Block a user