From 92100e27a03eaf26bfc6a1a1bb9d531e3d00a7fc Mon Sep 17 00:00:00 2001 From: grumbulon Date: Sat, 4 Feb 2023 20:41:16 -0500 Subject: [PATCH] add fs.go to internal, make makeLocal do the majority of lifting for tmp and perm files, made save() call makeLocal --- internal/api/fs.go | 69 +++++++++++++++++++++++++++++++++++++++ internal/api/types.go | 9 ++++- internal/api/zone.go | 76 ++++++------------------------------------- internal/util/fs.go | 40 ----------------------- 4 files changed, 87 insertions(+), 107 deletions(-) create mode 100644 internal/api/fs.go delete mode 100644 internal/util/fs.go diff --git a/internal/api/fs.go b/internal/api/fs.go new file mode 100644 index 0000000..492dd24 --- /dev/null +++ b/internal/api/fs.go @@ -0,0 +1,69 @@ +package api + +import ( + "errors" + "fmt" + "os" + "path/filepath" + + "git.freecumextremist.com/grumbulon/pomme/internal" +) + +var errEmptyFile = errors.New("will not save empty file to FS") + +// makeLocal takes a type path and then saves a zone file to either tmp or a permanent location +func makeLocal(where path, zone *ZoneRequest) error { + var ( + path string + file string + c *internal.Config + err error + ) + + if _, err := os.Stat(fmt.Sprintf(zone.FileName, zone.User)); !os.IsNotExist(err) { + return fmt.Errorf("file %s already exists: %w", zone.FileName, err) + } + + if len([]byte(zone.Body)) == 0 { + return errEmptyFile + } + + switch where { + case Tmp: + path = fmt.Sprintf("/tmp/tmpfile-%s-%s", zone.RawFileName, zone.User) + case Perm: + c, err = internal.ReadConfig() + if err != nil { + logHandler(genericResponseFields{"error": err.Error(), "message": "no config file defined"}) + + return fmt.Errorf("unable to parse directory: %w", err) + } + path = fmt.Sprintf("%s/%s/", c.ZoneDir, zone.RawFileName) + file = zone.RawFileName + if err = os.MkdirAll(path, 0o750); err != nil { + logHandler(genericResponseFields{"error": err.Error(), "message": "unable to make directory for zone files"}) + + return fmt.Errorf("unable to make zone directory: %w", err) + } + } + + f, err := os.Create(filepath.Clean(path + file)) //nolint: gosec + if err != nil { + return fmt.Errorf("failed to write file locally: %w", err) + } + + // close and remove the temporary file at the end of the program + defer func() { + if err = f.Close(); err != nil { + return + } + }() + + err = os.WriteFile(f.Name(), []byte(zone.Body), 0o600) + + if err != nil { + return fmt.Errorf("failed to write file locally: %w", err) + } + + return nil +} diff --git a/internal/api/types.go b/internal/api/types.go index 2efe5e3..8e40922 100644 --- a/internal/api/types.go +++ b/internal/api/types.go @@ -6,8 +6,15 @@ const ( keyPrincipalContextID key = iota ) +const ( + Tmp path = iota + Perm +) + type key int +type path int + // ZoneRequest represents a Zone file request. type ZoneRequest struct { *Zone @@ -31,7 +38,7 @@ type genericResponseFields map[string]any type ndr interface { parse() error - save() error + save(where path) error } var _ ndr = (*ZoneRequest)(nil) diff --git a/internal/api/zone.go b/internal/api/zone.go index 378d9f1..8cf9d8e 100644 --- a/internal/api/zone.go +++ b/internal/api/zone.go @@ -10,7 +10,6 @@ import ( "strings" "git.freecumextremist.com/grumbulon/pomme/internal" - "git.freecumextremist.com/grumbulon/pomme/internal/util" "github.com/go-chi/jwtauth/v5" "github.com/go-chi/render" "github.com/miekg/dns" @@ -64,8 +63,10 @@ func ReceiveFile(w http.ResponseWriter, r *http.Request) { return } - if err = util.MakeLocal(header.Filename, claims["username"].(string), b); err != nil { - APIError(w, r, genericResponseFields{"message": "internal server error", "status": http.StatusInternalServerError, "error": err.Error()}) + zoneFile := newDNSRequest(header.Filename, claims["username"].(string), b) + + if err := zoneFile.save(Tmp); err != nil { + APIError(w, r, genericResponseFields{"message": "Unable to save zonefile", "status": http.StatusInternalServerError, "error": err.Error()}) return } @@ -86,15 +87,13 @@ func ReceiveFile(w http.ResponseWriter, r *http.Request) { }, }) - zoneFile := newDNSRequest(header.Filename, claims["username"].(string)) - if err := zoneFile.parse(); err != nil { APIError(w, r, genericResponseFields{"message": "Unable to parse zonefile", "status": http.StatusInternalServerError, "error": err.Error()}) return } - if err := zoneFile.save(); err != nil { + if err := zoneFile.save(Perm); err != nil { APIError(w, r, genericResponseFields{"message": "Unable to save zonefile", "status": http.StatusInternalServerError, "error": err.Error()}) return @@ -111,12 +110,7 @@ func ReceiveFile(w http.ResponseWriter, r *http.Request) { render.JSON(w, r, resp) } -func newDNSRequest(filename string, user string) ndr { - dat, err := os.ReadFile(fmt.Sprintf("/tmp/tmpfile-%s-%s", filename, user)) - if err != nil { - return &ZoneRequest{} - } - +func newDNSRequest(filename string, user string, dat []byte) ndr { return &ZoneRequest{ User: user, Zone: &Zone{ @@ -142,61 +136,11 @@ func (zone *ZoneRequest) parse() error { return nil } -func (zone *ZoneRequest) save() error { - c, err := internal.ReadConfig() - if err != nil { - logHandler(genericResponseFields{"error": err.Error(), "message": "no config file defined"}) +func (zone *ZoneRequest) save(path) error { + // clean up the tmp file + defer os.Remove(filepath.Clean("/tmp/" + zone.FileName)) - return fmt.Errorf("unable to parse directory: %w", err) - } - - var path string = fmt.Sprintf("%s/%s/", c.ZoneDir, zone.RawFileName) - - var tmpPath string = fmt.Sprintf("/tmp/tmpfile-%s-%s", zone.RawFileName, zone.User) - - if err = os.MkdirAll(path, 0o750); err != nil { - logHandler(genericResponseFields{"error": err.Error(), "message": "unable to make directory for zone files"}) - - return fmt.Errorf("unable to make zone directory: %w", err) - } - - if _, err = os.Create(filepath.Clean(path + zone.RawFileName)); err != nil { - logHandler(genericResponseFields{"error": err.Error(), "message": "unable to save zonefile to directory"}) - - return fmt.Errorf("unable to save zonefile to directory: %w", err) - } - - f, err := os.Open(filepath.Clean(tmpPath)) - if err != nil { - logHandler(genericResponseFields{"error": err.Error(), "message": "unable to save zonefile to directory"}) - - return fmt.Errorf("unable to save zonefile to directory: %w", err) - } - - defer func() { - if err = f.Close(); err != nil { - logHandler(genericResponseFields{"message": "Error closing file", "error": err.Error()}) - } - - if err = os.Remove(filepath.Clean(tmpPath)); err != nil { - logHandler(genericResponseFields{"message": "Error removing tmp file", "error": err.Error()}) - } - }() - - b, err := io.ReadAll(f) - if err != nil { - logHandler(genericResponseFields{"error": err.Error(), "message": "unable to save zonefile to directory"}) - - return fmt.Errorf("unable to save zonefile to directory: %w", err) - } - - if err = os.WriteFile(path+zone.RawFileName, b, 0o600); err != nil { - logHandler(genericResponseFields{"error": err.Error(), "message": "unable to save zonefile to directory"}) - - return fmt.Errorf("unable to save zonefile to directory: %w", err) - } - - return nil + return makeLocal(Perm, zone) } func validateContentType(file io.Reader) bool { diff --git a/internal/util/fs.go b/internal/util/fs.go deleted file mode 100644 index d2048e4..0000000 --- a/internal/util/fs.go +++ /dev/null @@ -1,40 +0,0 @@ -package util - -import ( - "errors" - "fmt" - "os" -) - -var errEmptyFile = errors.New("will not save empty file to FS") - -func MakeLocal(filename, username string, buf []byte) error { - if _, err := os.Stat(fmt.Sprintf("/tmp/tmpfile-%s-%s", filename, username)); !os.IsNotExist(err) { - return fmt.Errorf("file %s already exists: %w", filename, err) - } - - if len(buf) == 0 { - return errEmptyFile - } - - f, err := os.Create("/tmp/tmpfile-" + filename + "-" + username) //nolint: gosec - // this is set to nolint because I am doing everything os.CreateTemp does but here since I don't like some of the limitations - if err != nil { - return fmt.Errorf("failed to write file locally: %w", err) - } - - // close and remove the temporary file at the end of the program - defer func() { - if err = f.Close(); err != nil { - return - } - }() - - err = os.WriteFile(f.Name(), buf, 0o600) - - if err != nil { - return fmt.Errorf("failed to write file locally: %w", err) - } - - return nil -}