diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..ffd2a4a2 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*.idea diff --git a/envsec/internal/filecache/filecache.go b/envsec/internal/filecache/filecache.go index d0e75fe3..ab700549 100644 --- a/envsec/internal/filecache/filecache.go +++ b/envsec/internal/filecache/filecache.go @@ -14,11 +14,8 @@ var NotFound = errors.New("not found") var Expired = errors.New("expired") type cache struct { - domain string -} - -func New(domain string) *cache { - return &cache{domain: domain} + domain string + cacheDir string } type data struct { @@ -26,6 +23,30 @@ type data struct { Exp time.Time } +type Option func(*cache) + +func New(domain string, opts ...Option) *cache { + result := &cache{domain: domain} + + var err error + result.cacheDir, err = os.UserCacheDir() + if err != nil { + result.cacheDir = "~/.cache" + } + + for _, opt := range opts { + opt(result) + } + + return result +} + +func WithCacheDir(dir string) Option { + return func(c *cache) { + c.cacheDir = dir + } +} + func (c *cache) Set(key string, val []byte, dur time.Duration) error { d, err := json.Marshal(data{Val: val, Exp: time.Now().Add(dur)}) if err != nil { @@ -65,11 +86,7 @@ func (c *cache) Get(key string) ([]byte, error) { } func (c *cache) filename(key string) string { - cacheDir, err := os.UserCacheDir() - if err != nil { - cacheDir = "~/.cache" - } - dir := filepath.Join(cacheDir, c.domain) + dir := filepath.Join(c.cacheDir, c.domain) _ = os.MkdirAll(dir, 0755) return filepath.Join(dir, key) } diff --git a/go.work.sum b/go.work.sum index d0a18c98..2066cdb3 100644 --- a/go.work.sum +++ b/go.work.sum @@ -1,16 +1,21 @@ +cloud.google.com/go/compute v1.20.1 h1:6aKEtlUiwEpJzM001l0yFkpXmUVXaN8W+fbkb2AZNbg= cloud.google.com/go/compute v1.20.1/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM= cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= +cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno= github.com/adrg/xdg v0.4.0 h1:RzRqFcjH4nE5C6oTAxhBtoE2IRyjBSa62SCbyPidvls= github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= +github.com/bwesterb/go-ristretto v1.2.3 h1:1w53tCkGhCQ5djbat3+MH0BAQ5Kfgbt56UZQ/JMzngw= +github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= github.com/cloudflare/ahocorasick v0.0.0-20210425175752-730270c3e184/go.mod h1:tGWUZLZp9ajsxUOnHmFFLnqnlKXsCn6GReG4jAD59H0= github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I= github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM= github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= +github.com/creack/pty v1.1.9 h1:uDmaGzcdjhF4i/plgjmEsriH11Y0o7RKapEf/LDaM3w= github.com/dop251/goja_nodejs v0.0.0-20210225215109-d91c329300e7 h1:tYwu/z8Y0NkkzGEh3z21mSWggMg4LwLRFucLS7TjARg= github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZifjYj7uP3BG/gKcuzL9xWVV/Y+cK33KM= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= @@ -44,6 +49,7 @@ github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g= github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasthttp v1.40.0/go.mod h1:t/G+3rLek+CyY9bnIE+YlMRddxVAAGjhxndDB4i4C0I= @@ -54,13 +60,19 @@ golang.org/x/crypto v0.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk= golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8= +golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU= +golang.org/x/term v0.12.0 h1:/ZfYdc3zq+q02Rv9vGqTeSItdzZTSNDmfTi0mBAuidU= golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= +gopkg.in/errgo.v2 v2.1.0 h1:0vLT13EuvQ0hNvakwLuFZ/jYrLp5F3kcWHXdRggjCE8= diff --git a/pkg/filecache/filecache.go b/pkg/filecache/filecache.go new file mode 100644 index 00000000..ab700549 --- /dev/null +++ b/pkg/filecache/filecache.go @@ -0,0 +1,92 @@ +// filecache is a simple local file-based cache +package filecache + +import ( + "encoding/json" + "os" + "path/filepath" + "time" + + "github.com/pkg/errors" +) + +var NotFound = errors.New("not found") +var Expired = errors.New("expired") + +type cache struct { + domain string + cacheDir string +} + +type data struct { + Val []byte + Exp time.Time +} + +type Option func(*cache) + +func New(domain string, opts ...Option) *cache { + result := &cache{domain: domain} + + var err error + result.cacheDir, err = os.UserCacheDir() + if err != nil { + result.cacheDir = "~/.cache" + } + + for _, opt := range opts { + opt(result) + } + + return result +} + +func WithCacheDir(dir string) Option { + return func(c *cache) { + c.cacheDir = dir + } +} + +func (c *cache) Set(key string, val []byte, dur time.Duration) error { + d, err := json.Marshal(data{Val: val, Exp: time.Now().Add(dur)}) + if err != nil { + return errors.WithStack(err) + } + + return errors.WithStack(os.WriteFile(c.filename(key), d, 0644)) +} + +func (c *cache) SetT(key string, val []byte, t time.Time) error { + d, err := json.Marshal(data{Val: val, Exp: t}) + if err != nil { + return errors.WithStack(err) + } + + return errors.WithStack(os.WriteFile(c.filename(key), d, 0644)) +} + +func (c *cache) Get(key string) ([]byte, error) { + path := c.filename(key) + if _, err := os.Stat(path); errors.Is(err, os.ErrNotExist) { + return nil, NotFound + } + + content, err := os.ReadFile(path) + if err != nil { + return nil, errors.WithStack(err) + } + d := data{} + if err := json.Unmarshal(content, &d); err != nil { + return nil, errors.WithStack(err) + } + if time.Now().After(d.Exp) { + return nil, Expired + } + return d.Val, nil +} + +func (c *cache) filename(key string) string { + dir := filepath.Join(c.cacheDir, c.domain) + _ = os.MkdirAll(dir, 0755) + return filepath.Join(dir, key) +}