Immutable value objects

master
Caj Larsson 3 years ago
parent ee58da4f2d
commit 5bad2c5335

@ -5,32 +5,36 @@ type FileSizeQuota struct {
CurrentUsage int64
}
func (f *FileSizeQuota) Allows(size int64) bool {
func (f FileSizeQuota) Allows(size int64) bool {
return f.Remaining() >= size
}
func (f *FileSizeQuota) Remaining() int64 {
func (f FileSizeQuota) Remaining() int64 {
return f.AllowanceKB - f.CurrentUsage
}
func (f *FileSizeQuota) Add(size int64) error {
func (f FileSizeQuota) Add(size int64) (*FileSizeQuota, error) {
if !f.Allows(size) {
return ErrExceedQuota
return nil, ErrExceedQuota
}
f.CurrentUsage += size
return nil
n := FileSizeQuota {
f.AllowanceKB,
f.CurrentUsage + size,
}
return &n, nil
}
func (f *FileSizeQuota) Remove(size int64) error {
func (f FileSizeQuota) Remove(size int64) (*FileSizeQuota, error) {
if size > f.CurrentUsage {
return ErrQuotaInvalid
return nil, ErrQuotaInvalid
}
f.CurrentUsage -= size
return nil
n := FileSizeQuota {
f.AllowanceKB,
f.CurrentUsage - size,
}
return &n, nil
}
type FileStat struct {

@ -15,23 +15,27 @@ func TestQuota(t *testing.T) {
func TestQuotaManipulation(t *testing.T) {
is := is.New(t)
quota := FileSizeQuota{1000, 0}
is.NoErr(quota.Add(500))
quota := &FileSizeQuota{1000, 0}
quota, err := quota.Add(500)
is.NoErr(err)
is.Equal(quota.CurrentUsage, int64(500))
is.NoErr(quota.Add(500))
quota, err = quota.Add(500)
is.NoErr(err)
is.Equal(quota.Add(1), ErrExceedQuota)
_ , err = quota.Add(1)
is.Equal(err, ErrExceedQuota)
is.Equal(quota.CurrentUsage, int64(1000))
is.Equal(quota.Remove(1001), ErrQuotaInvalid)
_ , err = quota.Remove(1001)
is.Equal(err, ErrQuotaInvalid)
is.Equal(quota.CurrentUsage, int64(1000))
is.NoErr(quota.Remove(1000))
quota, err = quota.Remove(1000)
is.NoErr(err)
is.Equal(quota.CurrentUsage, int64(0))
}

@ -61,7 +61,7 @@ func (s SwampFileService) getOrCreateNs(namespace_in string) *namespace.Namespac
func (s SwampFileService) SaveFile(ref swampfile.FileReference, src io.Reader, size int64) error {
ns := s.getOrCreateNs(ref.UserAgent)
err := ref.Clean(true)
r, err := ref.Clean(true)
if err != nil {
return err
@ -71,7 +71,7 @@ func (s SwampFileService) SaveFile(ref swampfile.FileReference, src io.Reader, s
return namespace.ErrExceedQuota
}
f, err := s.swamp_file_repo.Create(ref.Path, strconv.FormatInt(ns.ID, 10))
f, err := s.swamp_file_repo.Create(r.Path, strconv.FormatInt(ns.ID, 10))
if err != nil {
return err
@ -80,7 +80,7 @@ func (s SwampFileService) SaveFile(ref swampfile.FileReference, src io.Reader, s
written, err := io.CopyN(f, src, size)
if written < size {
s.swamp_file_repo.Delete(ref.Path, strconv.FormatInt(ns.ID, 10))
s.swamp_file_repo.Delete(r.Path, strconv.FormatInt(ns.ID, 10))
return swampfile.ErrContentSizeExaggerated
}
@ -89,12 +89,16 @@ func (s SwampFileService) SaveFile(ref swampfile.FileReference, src io.Reader, s
overread, err := src.Read(buf)
if overread > 0 || err != io.EOF {
s.swamp_file_repo.Delete(ref.Path, strconv.FormatInt(ns.ID, 10))
s.swamp_file_repo.Delete(r.Path, strconv.FormatInt(ns.ID, 10))
return swampfile.ErrContentSizeExceeded
}
f.Close()
ns.FileQuota.Add(size)
uq, err := ns.FileQuota.Add(size)
if err != nil {
return err
}
ns.FileQuota = *uq
ns.Usage = ns.Usage.Add(size)
ns.Upload = ns.Upload.Add(size)
s.namespace_repo.Update(ns.ID, *ns)
@ -105,13 +109,13 @@ func (s SwampFileService) SaveFile(ref swampfile.FileReference, src io.Reader, s
func (s SwampFileService) OpenOutFile(ref swampfile.FileReference) (swampfile.SwampOutFile, error) {
ns := s.getOrCreateNs(ref.UserAgent)
err := ref.Clean(true)
r, err := ref.Clean(true)
if err != nil {
return nil, err
}
f, err := s.swamp_file_repo.Open(ref.Path, strconv.FormatInt(ns.ID, 10))
f, err := s.swamp_file_repo.Open(r.Path, strconv.FormatInt(ns.ID, 10))
if err != nil {
return nil, err
@ -140,7 +144,11 @@ func (s SwampFileService) CleanUpExpiredFiles() error {
dfs, err := s.swamp_file_repo.DeleteOlderThan(strconv.FormatInt(ns.ID, 10), expiry)
for _, df := range dfs {
ns.FileQuota.Remove(df.Size)
dq, err := ns.FileQuota.Remove(df.Size)
if err != nil {
dq.CurrentUsage = 0
}
ns.FileQuota = *dq
}
if err != nil {

@ -36,14 +36,17 @@ type DeletedSwampFile struct {
Size int64
}
func (fr *FileReference) Clean(strict bool) error {
func (fr *FileReference) Clean(strict bool) (*FileReference, error) {
c := filepath.FromSlash(path.Clean("/" + strings.Trim(fr.Path, "/")))
if c != fr.Path && strict {
return ErrUnacceptablePath
return nil, ErrUnacceptablePath
}
fr.Path = c
n := FileReference {
c,
fr.UserAgent,
}
return nil
return &n, nil
}

@ -25,9 +25,9 @@ func TestSwampPathNotStrict(t *testing.T) {
"ns",
}
err := rf.Clean(false)
rc, err := rf.Clean(false)
is.NoErr(err)
is.Equal(rf.Path, tc.clean)
is.Equal(rc.Path, tc.clean)
}
}
@ -39,6 +39,6 @@ func TestSwampPathStrict(t *testing.T) {
"ns",
}
err := rf.Clean(true)
_, err := rf.Clean(true)
is.Equal(err, ErrUnacceptablePath)
}

Loading…
Cancel
Save