refactor, lint, refactor, lint, refactor, etc. Added config path for hashing secret, and a few other things

This commit is contained in:
grumbulon 2023-01-06 20:00:04 -05:00 committed by Gitea
parent 53e8d01cb9
commit 6e8f401e70
9 changed files with 163 additions and 143 deletions

View file

@ -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,
}

4
go.mod
View file

@ -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

16
go.sum
View file

@ -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=

View file

@ -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
}
}

View file

@ -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 {

View file

@ -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
}

View file

@ -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
}

32
internal/util/fs.go Normal file
View file

@ -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
}

View file

@ -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
}