From 6e8f401e70d6daee05d73a1ceb0ab2582c9fbc83 Mon Sep 17 00:00:00 2001 From: grumbulon Date: Fri, 6 Jan 2023 20:00:04 -0500 Subject: [PATCH] refactor, lint, refactor, lint, refactor, etc. Added config path for hashing secret, and a few other things --- cmd/pomme/main.go | 10 +++- go.mod | 4 +- go.sum | 16 ++---- internal/api/api.go | 13 ----- internal/api/jwt.go | 7 +-- internal/api/zone.go | 105 +++++++++++++++++--------------------- internal/configuration.go | 65 +++++++++++++++++++++++ internal/util/fs.go | 32 ++++++++++++ internal/zone.go | 54 -------------------- 9 files changed, 163 insertions(+), 143 deletions(-) create mode 100644 internal/util/fs.go delete mode 100644 internal/zone.go diff --git a/cmd/pomme/main.go b/cmd/pomme/main.go index 1fbf913..9b87980 100644 --- a/cmd/pomme/main.go +++ b/cmd/pomme/main.go @@ -6,12 +6,18 @@ import ( "time" "git.freecumextremist.com/grumbulon/pomme/frontend" + "git.freecumextremist.com/grumbulon/pomme/internal" "git.freecumextremist.com/grumbulon/pomme/internal/api" "github.com/go-chi/chi/v5" "github.com/go-chi/chi/v5/middleware" ) func main() { + config, err := internal.ReadConfig() + if err != nil { + panic(err) + } + pomme := chi.NewRouter() pomme.Use(middleware.Logger) pomme.Use(middleware.GetHead) @@ -21,13 +27,13 @@ func main() { pomme.Mount("/api", api.API()) log.Println("\t-------------------------------------") - log.Println("\t\tRunning on port 3000") + log.Println("\t\tRunning on port " + config.Port) log.Println("\t-------------------------------------") s := &http.Server{ ReadTimeout: 3 * time.Second, WriteTimeout: 15 * time.Second, - Addr: ":3000", + Addr: ":" + config.Port, Handler: pomme, } diff --git a/go.mod b/go.mod index f276821..55f31b2 100644 --- a/go.mod +++ b/go.mod @@ -6,14 +6,13 @@ require ( github.com/glebarez/sqlite v1.6.0 github.com/go-chi/chi/v5 v5.0.8 github.com/go-chi/jwtauth/v5 v5.1.0 - github.com/go-chi/render v1.0.2 github.com/miekg/dns v1.1.50 golang.org/x/crypto v0.5.0 gorm.io/gorm v1.24.3 ) require ( - github.com/ajg/form v1.5.1 // indirect + github.com/adrg/xdg v0.4.0 github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 // indirect github.com/glebarez/go-sqlite v1.20.0 // indirect github.com/goccy/go-json v0.10.0 // indirect @@ -32,6 +31,7 @@ require ( golang.org/x/net v0.5.0 // indirect golang.org/x/sys v0.4.0 // indirect golang.org/x/tools v0.1.12 // indirect + gopkg.in/yaml.v3 v3.0.1 modernc.org/libc v1.21.5 // indirect modernc.org/mathutil v1.5.0 // indirect modernc.org/memory v1.4.0 // indirect diff --git a/go.sum b/go.sum index f7f2bfa..2c09ca3 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,5 @@ -github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU= -github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= +github.com/adrg/xdg v0.4.0 h1:RzRqFcjH4nE5C6oTAxhBtoE2IRyjBSa62SCbyPidvls= +github.com/adrg/xdg v0.4.0/go.mod h1:N6ag73EX4wyxeaoeHctc1mas01KZgsj5tYiAIwqJE/E= github.com/chzyer/logex v1.2.0/go.mod h1:9+9sk7u7pGNWYMkh0hdiL++6OeibzJccyQU4p4MedaY= github.com/chzyer/readline v1.5.0/go.mod h1:x22KAscuvRqlLoK9CsoYsmxoXZMMFVyOl86cAH8qUic= github.com/chzyer/test v0.0.0-20210722231415-061457976a23/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= @@ -18,8 +18,6 @@ github.com/go-chi/chi/v5 v5.0.8 h1:lD+NLqFcAi1ovnVZpsnObHGW4xb4J8lNmoYVfECH1Y0= github.com/go-chi/chi/v5 v5.0.8/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= github.com/go-chi/jwtauth/v5 v5.1.0 h1:wJyf2YZ/ohPvNJBwPOzZaQbyzwgMZZceE1m8FOzXLeA= github.com/go-chi/jwtauth/v5 v5.1.0/go.mod h1:MA93hc1au3tAQwCKry+fI4LqJ5MIVN4XSsglOo+lSc8= -github.com/go-chi/render v1.0.2 h1:4ER/udB0+fMWB2Jlf15RV3F4A2FDuYi/9f+lFttR/Lg= -github.com/go-chi/render v1.0.2/go.mod h1:/gr3hVkmYR0YlEy3LxCuVRFzEu9Ruok+gFqbIofjao0= github.com/goccy/go-json v0.9.11/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/goccy/go-json v0.10.0 h1:mXKd9Qw4NuzShiRlOXKews24ufknHO7gx30lsDyokKA= github.com/goccy/go-json v0.10.0/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= @@ -61,6 +59,7 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= @@ -71,8 +70,6 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20220427172511-eb4f295cb31f/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.4.0 h1:UVQgzMY87xqpKNgb+kDsll2Igd33HszWHFLmpaRMq/8= -golang.org/x/crypto v0.4.0/go.mod h1:3quD/ATkf6oY+rnes5c3ExXTbLc8mueNue5/DoinL80= golang.org/x/crypto v0.5.0 h1:U/0M97KRkSFvyD/3FSmdP5W5swImpNgle/EHFhOsQPE= golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= @@ -85,8 +82,6 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.3.0 h1:VWL6FNY2bEEmsGVKabSlHu5Irp34xmMRoqb/9lF9lxk= -golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= golang.org/x/net v0.5.0 h1:GyT4nK/YDHSqa1c4753ouYCDajOYKTja9Xb/OHtgvSw= golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -102,10 +97,9 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.3.0 h1:w8ZOecv6NaNa/zC8944JTU3vz4u6Lagfk4RPQxv92NQ= -golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18= golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -122,11 +116,11 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gorm.io/gorm v1.24.2 h1:9wR6CFD+G8nOusLdvkZelOEhpJVwwHzpQOUM+REd6U0= gorm.io/gorm v1.24.2/go.mod h1:DVrVomtaYTbqs7gB/x2uVvqnXzv0nqjB396B8cG4dBA= gorm.io/gorm v1.24.3 h1:WL2ifUmzR/SLp85CSURAfybcHnGZ+yLSGSxgYXlFBHg= gorm.io/gorm v1.24.3/go.mod h1:DVrVomtaYTbqs7gB/x2uVvqnXzv0nqjB396B8cG4dBA= diff --git a/internal/api/api.go b/internal/api/api.go index f44f55f..8ecb637 100644 --- a/internal/api/api.go +++ b/internal/api/api.go @@ -43,7 +43,6 @@ func API() http.Handler { api.Use(jwtauth.Authenticator) api.With(SetDBMiddleware).Post("/upload", RecieveFile) - api.Get("/private", AuthTest) }) // Open routes @@ -56,15 +55,3 @@ func API() http.Handler { return api } - -// AuthTest is for testing protected routes. -func AuthTest(w http.ResponseWriter, r *http.Request) { - _, claims, _ := jwtauth.FromContext(r.Context()) - - _, err := w.Write([]byte(fmt.Sprintf("protected area. hi %v", claims["username"]))) - if err != nil { - http.Error(w, "internal server error", http.StatusInternalServerError) - - return - } -} diff --git a/internal/api/jwt.go b/internal/api/jwt.go index eee1a3f..fbe900a 100644 --- a/internal/api/jwt.go +++ b/internal/api/jwt.go @@ -3,15 +3,16 @@ package api import ( "log" + "git.freecumextremist.com/grumbulon/pomme/internal" "github.com/go-chi/jwtauth/v5" ) var tokenAuth *jwtauth.JWTAuth -const secret = "piss" - func init() { - tokenAuth = jwtauth.New("HS256", []byte(secret), nil) + if config, err := internal.ReadConfig(); err == nil { + tokenAuth = jwtauth.New("HS256", []byte(config.HashingSecret), nil) + } } func makeToken(username string) string { diff --git a/internal/api/zone.go b/internal/api/zone.go index 664b8eb..bba9d24 100644 --- a/internal/api/zone.go +++ b/internal/api/zone.go @@ -2,18 +2,32 @@ package api import ( "bytes" + "fmt" "io" "log" "net/http" - "os" "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" "gorm.io/gorm" ) +// ZoneRequest represents a Zone file request. +type ZoneRequest struct { + *Zone + + User string `json:"user,omitempty" gorm:"foreignKey:username;references:User"` +} + +// Zone struct represents a zonefile. +type Zone struct { + gorm.Model + FileName string `json:"name"` + Body string `json:"body"` +} + func RecieveFile(w http.ResponseWriter, r *http.Request) { _, claims, _ := jwtauth.FromContext(r.Context()) @@ -32,87 +46,62 @@ func RecieveFile(w http.ResponseWriter, r *http.Request) { name := strings.Split(header.Filename, ".") - _, err = io.Copy(&buf, file) - - if err != nil { + if _, err = io.Copy(&buf, file); err != nil { http.Error(w, "internal server error", http.StatusInternalServerError) return } - f, err := os.CreateTemp("", "tmpfile-") - if err != nil { + if err = util.MakeLocal(name[0], claims["username"].(string), buf); err != nil { http.Error(w, "internal server error", http.StatusInternalServerError) return } - log.Println(f.Name()) - - // close and remove the temporary file at the end of the program - defer func() { - if err = f.Close(); err != nil { - http.Error(w, "internal server error", http.StatusInternalServerError) - - return - } - }() - - defer os.Remove(f.Name()) //nolint: errcheck - - // write data to the temporary file - if _, err = f.Write(buf.Bytes()); err != nil { - http.Error(w, "internal server error", http.StatusInternalServerError) - - return - } - - err = os.WriteFile(f.Name(), buf.Bytes(), 0o600) - - if err != nil { - http.Error(w, "internal server error", http.StatusInternalServerError) - - return - } + // ugly + zoneReq := newZoneRequest(fmt.Sprintf("tmpfile-%s-%s", name[0], claims["username"].(string)), + claims["username"].(string), + ) buf.Reset() - zoneReq := newZoneRequest(name[0], claims["username"].(string)) - db, ok := r.Context().Value(keyPrincipalContextID).(*gorm.DB) if !ok { http.Error(w, "internal server error", http.StatusInternalServerError) + + return } db.Create(zoneReq) - parseFile(zoneReq) + err = zoneReq.Parse() + if err != nil { + http.Error(w, "internal server error", http.StatusInternalServerError) + + return + } } -func newZoneRequest(filename string, user string) *internal.ZoneRequest { - return &internal.ZoneRequest{ +func newZoneRequest(filename string, user string) *ZoneRequest { + return &ZoneRequest{ User: user, - Zone: &internal.Zone{ - FileName: filename, - RequestID: "1", - Body: "aaaaaaaaaaaaaaaaa", + Zone: &Zone{ + FileName: filename, }, } } -func parseFile(z *internal.ZoneRequest) bool { - err := z.Parse() +// Parse will be used to parse zonefiles. +func (zone *ZoneRequest) Parse() error { + zp := dns.NewZoneParser(strings.NewReader(zone.Body), "", "") - return err == nil -} - -// Ingest is a function to ingest Zonefiles. -func Ingest(w http.ResponseWriter, r *http.Request) { - _ = &internal.ZoneRequest{} - - // todo write to database, maybe? - - // todo -- add functions to apply to master zonefile if above check is OK. - - render.Status(r, http.StatusAccepted) + for rr, ok := zp.Next(); ok; rr, ok = zp.Next() { + log.Println(rr) + } + + if err := zp.Err(); err != nil { + return fmt.Errorf("unable to parse Zonefile: %w", err) + } + + return nil } diff --git a/internal/configuration.go b/internal/configuration.go index 5bf0569..55f1718 100644 --- a/internal/configuration.go +++ b/internal/configuration.go @@ -1 +1,66 @@ package internal + +import ( + "fmt" + "os" + "path/filepath" + + "github.com/adrg/xdg" + "gopkg.in/yaml.v3" + "gorm.io/gorm" +) + +// User struct represents a user in the database. +type User struct { + gorm.Model + Username string + Password string + HashedPassword string +} + +// Response struct represents a json response. +type Response struct { + Username string `json:"username,omitempty"` + Message string `json:"message,omitempty"` + HTTPResponse int `json:"status,omitempty"` +} + +// ZoneRequest represents a Zone file request. +type ZoneRequest struct { + *Zone + + User string `json:"user,omitempty" gorm:"foreignKey:username;references:User"` +} + +// Zone struct represents a zonefile in the database. +type Zone struct { + gorm.Model + FileName string `json:"name"` + Body string `json:"body"` +} + +type Config struct { + Server string + HashingSecret string + Port string +} + +var config Config + +func ReadConfig() (*Config, error) { + configPath := xdg.ConfigHome + "/pomme/config.yaml" + + if configPath != "" { + data, err := os.ReadFile(filepath.Clean(configPath)) + if err != nil { + return &Config{}, fmt.Errorf("unable to read config file: %w", err) + } + + err = yaml.Unmarshal(data, &config) + if err != nil { + return &Config{}, fmt.Errorf("unable to unmarshal config file: %w", err) + } + } + + return &config, nil +} diff --git a/internal/util/fs.go b/internal/util/fs.go new file mode 100644 index 0000000..4358573 --- /dev/null +++ b/internal/util/fs.go @@ -0,0 +1,32 @@ +package util + +import ( + "bytes" + "fmt" + "os" +) + +func MakeLocal(filename, username string, buf bytes.Buffer) error { + defer buf.Reset() + + 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.Bytes(), 0o600) + + if err != nil { + return fmt.Errorf("failed to write file locally: %w", err) + } + + return nil +} diff --git a/internal/zone.go b/internal/zone.go deleted file mode 100644 index aa38af5..0000000 --- a/internal/zone.go +++ /dev/null @@ -1,54 +0,0 @@ -package internal - -import ( - "fmt" - "log" - "strings" - - "github.com/miekg/dns" - "gorm.io/gorm" -) - -// ZoneRequest represents a Zone file request. -type ZoneRequest struct { - *Zone - - User string `json:"user,omitempty" gorm:"foreignKey:username;references:User"` -} - -// Zone struct represents a zonefile. -type Zone struct { - FileName string `json:"name"` - RequestID string `json:"id"` - Body string `json:"body"` -} - -// User struct represents a user. -type User struct { - gorm.Model - Username string - Password string - HashedPassword string -} - -// Response struct represents a json response. -type Response struct { - Username string `json:"username,omitempty"` - Message string `json:"message,omitempty"` - HTTPResponse int `json:"status,omitempty"` -} - -// Parse will be used to parse zonefiles. -func (zone *ZoneRequest) Parse() error { - zp := dns.NewZoneParser(strings.NewReader(zone.Body), "", "") - - for rr, ok := zp.Next(); ok; rr, ok = zp.Next() { - log.Println(rr) - } - - if err := zp.Err(); err != nil { - return fmt.Errorf("unable to parse Zonefile: %w", err) - } - - return nil -}