mirror of
https://git.freecumextremist.com/grumbulon/pomme.git
synced 2024-12-22 23:50:43 +00:00
Merge pull request 'feat(backend): zonefile parsing and other enhancements' (#12) from zonefile into master
Reviewed-on: https://git.freecumextremist.com/grumbulon/pomme/pulls/12
This commit is contained in:
commit
4f0a999e08
14 changed files with 405 additions and 142 deletions
4
.gitignore
vendored
4
.gitignore
vendored
|
@ -23,4 +23,6 @@ go.work
|
|||
|
||||
pomme
|
||||
test.db
|
||||
.dccache
|
||||
test.sqlite
|
||||
.dccache
|
||||
config.yaml
|
|
@ -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,
|
||||
}
|
||||
|
||||
|
|
3
config.sample.yaml
Normal file
3
config.sample.yaml
Normal file
|
@ -0,0 +1,3 @@
|
|||
server: example.com # does nothing yet
|
||||
hashingsecret: PasswordHashingSecret
|
||||
port: 3008 # port the server runs on
|
12
go.mod
12
go.mod
|
@ -6,16 +6,21 @@ 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/mattn/go-colorable v0.1.12 // indirect
|
||||
github.com/rs/zerolog v1.27.0 // indirect
|
||||
)
|
||||
|
||||
require (
|
||||
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/go-chi/httplog v0.2.5
|
||||
github.com/goccy/go-json v0.10.0 // indirect
|
||||
github.com/google/uuid v1.3.0 // indirect
|
||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||
|
@ -26,12 +31,13 @@ require (
|
|||
github.com/lestrrat-go/iter v1.0.2 // indirect
|
||||
github.com/lestrrat-go/jwx/v2 v2.0.8 // indirect
|
||||
github.com/lestrrat-go/option v1.0.1 // indirect
|
||||
github.com/mattn/go-isatty v0.0.16 // indirect
|
||||
github.com/mattn/go-isatty v0.0.17 // indirect
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 // indirect
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
|
||||
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
|
||||
|
|
33
go.sum
33
go.sum
|
@ -1,8 +1,9 @@
|
|||
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=
|
||||
github.com/coreos/go-systemd/v22 v22.3.3-0.20220203105225-a9a7ef127534/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
|
@ -14,15 +15,17 @@ github.com/glebarez/go-sqlite v1.20.0 h1:6D9uRXq3Kd+W7At+hOU2eIAeahv6qcYfO8jzmvb
|
|||
github.com/glebarez/go-sqlite v1.20.0/go.mod h1:uTnJoqtwMQjlULmljLT73Cg7HB+2X6evsBHODyyq1ak=
|
||||
github.com/glebarez/sqlite v1.6.0 h1:ZpvDLv4zBi2cuuQPitRiVz/5Uh6sXa5d8eBu0xNTpAo=
|
||||
github.com/glebarez/sqlite v1.6.0/go.mod h1:6D6zPU/HTrFlYmVDKqBJlmQvma90P6r7sRRdkUUZOYk=
|
||||
github.com/go-chi/chi/v5 v5.0.7/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
|
||||
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/httplog v0.2.5 h1:S02eG9NTrB/9kk3Q3RA3F6CR2b+v8WzB8IxK+zq3dBo=
|
||||
github.com/go-chi/httplog v0.2.5/go.mod h1:/pIXuFSrOdc5heKIJRA5Q2mW7cZCI2RySqFZNFoZjKg=
|
||||
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=
|
||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo=
|
||||
|
@ -48,19 +51,28 @@ github.com/lestrrat-go/jwx/v2 v2.0.8/go.mod h1:zLxnyv9rTlEvOUHbc48FAfIL8iYu2hHvI
|
|||
github.com/lestrrat-go/option v1.0.0/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I=
|
||||
github.com/lestrrat-go/option v1.0.1 h1:oAzP2fvZGQKWkvHa1/SAcFolBEca1oN+mQ7eooNBEYU=
|
||||
github.com/lestrrat-go/option v1.0.1/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I=
|
||||
github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ=
|
||||
github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40=
|
||||
github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
|
||||
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng=
|
||||
github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/mattn/go-sqlite3 v1.14.15/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
|
||||
github.com/miekg/dns v1.1.50 h1:DQUfb9uc6smULcREF09Uc+/Gd46YWqJd5DbpPE9xkcA=
|
||||
github.com/miekg/dns v1.1.50/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6OkFY5QxjkYwrChwuRruF69c169dPK26NUlk=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||
github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
|
||||
github.com/rs/zerolog v1.27.0 h1:1T7qCieN22GVc8S4Q2yuexzBb1EqjbgjSH9RohbMjKs=
|
||||
github.com/rs/zerolog v1.27.0/go.mod h1:7frBqO0oezxmnO7GF86FY++uy8I0Tk/If5ni1G9Qc0U=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
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 +83,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 +95,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 +110,11 @@ 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-20210927094055-39ccf1dd6fa6/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-20220715151400-c0bba94af5f8/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 +131,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=
|
||||
|
|
|
@ -6,11 +6,10 @@ import (
|
|||
"net/http"
|
||||
"time"
|
||||
|
||||
"git.freecumextremist.com/grumbulon/pomme/internal"
|
||||
"git.freecumextremist.com/grumbulon/pomme/internal/db"
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/go-chi/httplog"
|
||||
"github.com/go-chi/jwtauth/v5"
|
||||
"github.com/go-chi/render"
|
||||
)
|
||||
|
||||
type key int
|
||||
|
@ -19,8 +18,8 @@ const (
|
|||
keyPrincipalContextID key = iota
|
||||
)
|
||||
|
||||
// SetDBMiddleware is the http Handler func for the GORM middleware with context.
|
||||
func SetDBMiddleware(next http.Handler) http.Handler {
|
||||
// setDBMiddleware is the http Handler func for the GORM middleware with context.
|
||||
func setDBMiddleware(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
db := db.InitDb()
|
||||
timeoutContext, cancelContext := context.WithTimeout(context.Background(), time.Second)
|
||||
|
@ -30,11 +29,27 @@ func SetDBMiddleware(next http.Handler) http.Handler {
|
|||
})
|
||||
}
|
||||
|
||||
func basicAuthFailed(w http.ResponseWriter, realm string) {
|
||||
w.Header().Add("WWW-Authenticate", fmt.Sprintf(`Basic realm="%s"`, realm))
|
||||
// handlers for very common errors.
|
||||
func authFailed(w http.ResponseWriter, realm string) {
|
||||
w.Header().Set("Content-Type", "text/plain; charset=utf-8")
|
||||
w.Header().Set("X-Content-Type-Options", "nosniff")
|
||||
w.Header().Add("WWW-Authenticate", fmt.Sprintf(`Realm="%s"`, realm))
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
}
|
||||
|
||||
func internalServerError(w http.ResponseWriter, errMsg string) {
|
||||
logger := httplog.NewLogger("Pomme", httplog.Options{
|
||||
JSON: true,
|
||||
})
|
||||
|
||||
w.Header().Set("Content-Type", "text/plain; charset=utf-8")
|
||||
w.Header().Set("X-Content-Type-Options", "nosniff")
|
||||
w.Header().Add("Internal Server Error", errMsg)
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
|
||||
logger.Error().Msg(errMsg)
|
||||
}
|
||||
|
||||
// API subroute handler.
|
||||
func API() http.Handler {
|
||||
api := chi.NewRouter()
|
||||
|
@ -44,40 +59,17 @@ func API() http.Handler {
|
|||
api.Use(jwtauth.Verifier(tokenAuth))
|
||||
|
||||
api.Use(jwtauth.Authenticator)
|
||||
api.Post("/check", Ingest)
|
||||
api.Get("/private", AuthTest)
|
||||
api.With(setDBMiddleware).Post("/upload", ReceiveFile)
|
||||
api.With(setDBMiddleware).Post("/parse", ZoneFiles)
|
||||
})
|
||||
|
||||
// Open routes
|
||||
api.Group(func(api chi.Router) {
|
||||
api.Use(SetDBMiddleware)
|
||||
api.With(SetDBMiddleware).Post("/create", NewUser)
|
||||
api.With(SetDBMiddleware).Post("/login", Login)
|
||||
api.Use(setDBMiddleware)
|
||||
api.With(setDBMiddleware).Post("/create", NewUser)
|
||||
api.With(setDBMiddleware).Post("/login", Login)
|
||||
api.Post("/logout", Logout)
|
||||
})
|
||||
|
||||
return api
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,9 +14,15 @@ import (
|
|||
func Login(w http.ResponseWriter, r *http.Request) {
|
||||
var result internal.User
|
||||
|
||||
if _, err := r.Cookie("jwt"); err == nil {
|
||||
http.Error(w, "Logged in", http.StatusCreated)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
err := r.ParseForm()
|
||||
if err != nil {
|
||||
http.Error(w, "Unable to parse request", http.StatusInternalServerError)
|
||||
internalServerError(w, "unable to parse request")
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -26,20 +32,20 @@ func Login(w http.ResponseWriter, r *http.Request) {
|
|||
password := r.Form.Get("password")
|
||||
|
||||
if username == "" {
|
||||
http.Error(w, "No username provided", http.StatusInternalServerError) // this should prob be handled by the frontend
|
||||
internalServerError(w, "no username provided") // this should prob be handled by the frontend
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if password == "" {
|
||||
http.Error(w, "No password provided", http.StatusInternalServerError) // this should prob be handled by the frontend
|
||||
internalServerError(w, "no password provided") // this should prob be handled by the frontend
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
db, ok := r.Context().Value(keyPrincipalContextID).(*gorm.DB)
|
||||
if !ok {
|
||||
http.Error(w, "internal server error", http.StatusInternalServerError)
|
||||
internalServerError(w, "DB connection failed")
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -47,7 +53,7 @@ func Login(w http.ResponseWriter, r *http.Request) {
|
|||
db.Where("username = ?", username).First(&result)
|
||||
|
||||
if result.Username == "" {
|
||||
http.Error(w, "login failed", http.StatusUnauthorized)
|
||||
authFailed(w, "login")
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -55,12 +61,17 @@ func Login(w http.ResponseWriter, r *http.Request) {
|
|||
err = bcrypt.CompareHashAndPassword([]byte(result.HashedPassword), []byte(password))
|
||||
|
||||
if err != nil {
|
||||
basicAuthFailed(w, "user")
|
||||
authFailed(w, "login")
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
token := makeToken(username)
|
||||
token, err := makeToken(username)
|
||||
if err != nil {
|
||||
internalServerError(w, err.Error())
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
http.SetCookie(w, &http.Cookie{
|
||||
HttpOnly: true,
|
||||
|
@ -80,7 +91,7 @@ func Login(w http.ResponseWriter, r *http.Request) {
|
|||
})
|
||||
|
||||
if err != nil {
|
||||
http.Error(w, "internal server error", http.StatusInternalServerError)
|
||||
internalServerError(w, "internal server error")
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -98,6 +109,7 @@ func Logout(w http.ResponseWriter, r *http.Request) {
|
|||
Name: "jwt",
|
||||
Value: "",
|
||||
})
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
err := json.NewEncoder(w).Encode(
|
||||
|
@ -106,7 +118,7 @@ func Logout(w http.ResponseWriter, r *http.Request) {
|
|||
HTTPResponse: 200,
|
||||
})
|
||||
if err != nil {
|
||||
http.Error(w, "internal server error", http.StatusInternalServerError)
|
||||
internalServerError(w, "internal server error")
|
||||
|
||||
return
|
||||
}
|
||||
|
|
|
@ -1,24 +1,29 @@
|
|||
package api
|
||||
|
||||
import (
|
||||
"log"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"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 {
|
||||
_, tokenString, err := tokenAuth.Encode(map[string]interface{}{"username": username, "admin": "false"})
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
func makeToken(username string) (tokenString string, err error) {
|
||||
claim := map[string]interface{}{"username": username, "admin": false}
|
||||
|
||||
jwtauth.SetExpiry(claim, time.Now().Add(time.Hour))
|
||||
|
||||
if _, tokenString, err = tokenAuth.Encode(claim); err == nil {
|
||||
return
|
||||
}
|
||||
|
||||
return tokenString
|
||||
return "", fmt.Errorf("unable to generate JWT: %w", err)
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
"fmt"
|
||||
"math/big"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"git.freecumextremist.com/grumbulon/pomme/internal"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
|
@ -16,14 +17,14 @@ import (
|
|||
func NewUser(w http.ResponseWriter, r *http.Request) {
|
||||
db, ok := r.Context().Value(keyPrincipalContextID).(*gorm.DB)
|
||||
if !ok {
|
||||
http.Error(w, "internal server error", http.StatusInternalServerError)
|
||||
internalServerError(w, "internal server error")
|
||||
}
|
||||
|
||||
var result internal.User
|
||||
|
||||
err := r.ParseForm()
|
||||
if err != nil {
|
||||
http.Error(w, "Unable to parse request", http.StatusInternalServerError)
|
||||
internalServerError(w, "unable to parse request")
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -37,7 +38,7 @@ func NewUser(w http.ResponseWriter, r *http.Request) {
|
|||
password := r.Form.Get("password")
|
||||
|
||||
if password == "" {
|
||||
http.Error(w, "No password entered", http.StatusInternalServerError)
|
||||
internalServerError(w, "no password provided")
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -45,33 +46,54 @@ func NewUser(w http.ResponseWriter, r *http.Request) {
|
|||
db.Where("username = ?", username).First(&result)
|
||||
|
||||
if result.Username != "" {
|
||||
http.Error(w, "User already exists", http.StatusInternalServerError)
|
||||
internalServerError(w, "user already exists")
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
authFailed(w, "login")
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
db.Create(&internal.User{Username: username, HashedPassword: string(hashedPassword)})
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
token, err := makeToken(username)
|
||||
if err != nil {
|
||||
internalServerError(w, "internal server error")
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
http.SetCookie(w, &http.Cookie{
|
||||
HttpOnly: true,
|
||||
Expires: time.Now().Add(1 * time.Hour),
|
||||
MaxAge: 3600,
|
||||
SameSite: http.SameSiteLaxMode,
|
||||
// Uncomment below for HTTPS:
|
||||
// Secure: true,
|
||||
Name: "jwt", // Must be named "jwt" or else the token cannot be searched for by jwtauth.Verifier.
|
||||
Value: token,
|
||||
})
|
||||
|
||||
w.WriteHeader(http.StatusCreated)
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
err = json.NewEncoder(w).Encode(
|
||||
internal.Response{
|
||||
Username: username,
|
||||
HTTPResponse: http.StatusCreated,
|
||||
Message: "Successfully created account and logged in",
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
http.Error(w, "internal server error", http.StatusInternalServerError)
|
||||
internalServerError(w, "internal server error")
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
http.Redirect(w, r, "/", http.StatusSeeOther)
|
||||
}
|
||||
|
||||
func autoUname() string {
|
||||
|
|
161
internal/api/zone.go
Normal file
161
internal/api/zone.go
Normal file
|
@ -0,0 +1,161 @@
|
|||
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/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"`
|
||||
RawFileName string `json:"rawname"`
|
||||
Body string `json:"body,omitempty"`
|
||||
}
|
||||
|
||||
func ReceiveFile(w http.ResponseWriter, r *http.Request) {
|
||||
_, claims, _ := jwtauth.FromContext(r.Context())
|
||||
|
||||
var buf bytes.Buffer
|
||||
|
||||
r.Body = http.MaxBytesReader(w, r.Body, 1*1024*1024) // approx 1 mb max upload
|
||||
|
||||
file, header, err := r.FormFile("file")
|
||||
if err != nil {
|
||||
internalServerError(w, fmt.Sprintf("file upload failed: %v", err))
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
defer file.Close() //nolint: errcheck
|
||||
|
||||
name := strings.Split(header.Filename, ".")
|
||||
|
||||
if _, err = io.Copy(&buf, file); err != nil {
|
||||
internalServerError(w, "internal server error")
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if err = util.MakeLocal(name[0], claims["username"].(string), buf); err != nil {
|
||||
internalServerError(w, "internal server error")
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
db, ok := r.Context().Value(keyPrincipalContextID).(*gorm.DB)
|
||||
if !ok {
|
||||
internalServerError(w, "internal server error")
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
db.Create(
|
||||
&ZoneRequest{
|
||||
User: claims["username"].(string),
|
||||
Zone: &Zone{
|
||||
FileName: fmt.Sprintf("tmpfile-%s-%s", name[0], claims["username"].(string)),
|
||||
RawFileName: name[0],
|
||||
},
|
||||
})
|
||||
|
||||
buf.Reset()
|
||||
}
|
||||
|
||||
func ZoneFiles(w http.ResponseWriter, r *http.Request) {
|
||||
var result internal.ZoneRequest
|
||||
|
||||
_, claims, _ := jwtauth.FromContext(r.Context())
|
||||
|
||||
err := r.ParseForm()
|
||||
if err != nil {
|
||||
internalServerError(w, "unable to parse request")
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
filename := r.Form.Get("filename")
|
||||
|
||||
if filename == "" {
|
||||
internalServerError(w, "no filename parsed")
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
db, ok := r.Context().Value(keyPrincipalContextID).(*gorm.DB)
|
||||
if !ok {
|
||||
internalServerError(w, "internal server error")
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
db.Where(ZoneRequest{
|
||||
Zone: &Zone{
|
||||
RawFileName: filename,
|
||||
},
|
||||
User: claims["username"].(string),
|
||||
}).First(&result)
|
||||
|
||||
if result == (internal.ZoneRequest{}) {
|
||||
internalServerError(w, "internal server error")
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
zoneFile := newZoneRequest(result.RawFileName, claims["username"].(string))
|
||||
|
||||
if err := zoneFile.Parse(); err != nil {
|
||||
internalServerError(w, fmt.Sprintf("unable to parse zonefile: %v", err))
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func newZoneRequest(filename string, user string) *ZoneRequest {
|
||||
dat, err := os.ReadFile(fmt.Sprintf("/tmp/tmpfile-%s-%s", filename, user))
|
||||
if err != nil {
|
||||
return &ZoneRequest{}
|
||||
}
|
||||
|
||||
return &ZoneRequest{
|
||||
User: user,
|
||||
Zone: &Zone{
|
||||
FileName: fmt.Sprintf("tmpfile-%s-%s", filename, user),
|
||||
RawFileName: filename,
|
||||
Body: string(dat),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
|
@ -1 +1,77 @@
|
|||
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"`
|
||||
RawFileName string `json:"rawfilename"`
|
||||
Body string `json:"body"`
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
Server string
|
||||
HashingSecret string
|
||||
Port string
|
||||
}
|
||||
|
||||
var config Config
|
||||
|
||||
func ReadConfig() (*Config, error) {
|
||||
var (
|
||||
data []byte
|
||||
err error
|
||||
defaultConfigPath string
|
||||
)
|
||||
|
||||
defaultConfigPath = xdg.ConfigHome + "/pomme/config.yaml"
|
||||
|
||||
if data, err = os.ReadFile(filepath.Clean(defaultConfigPath)); err == nil {
|
||||
if err = yaml.Unmarshal(data, &config); err != nil {
|
||||
return &Config{}, fmt.Errorf("unable to unmarshal config file: %w", err)
|
||||
}
|
||||
|
||||
return &config, nil
|
||||
}
|
||||
|
||||
if data, err = os.ReadFile(filepath.Clean("./config.yaml")); err == nil {
|
||||
if err = yaml.Unmarshal(data, &config); err != nil {
|
||||
return &Config{}, fmt.Errorf("unable to unmarshal config file: %w", err)
|
||||
}
|
||||
|
||||
return &config, nil
|
||||
}
|
||||
|
||||
return &Config{}, fmt.Errorf("unable to read config file: %w", err)
|
||||
}
|
||||
|
|
|
@ -8,13 +8,13 @@ import (
|
|||
|
||||
// InitDb is the init function for the database.
|
||||
func InitDb() *gorm.DB {
|
||||
db, err := gorm.Open(sqlite.Open("test.db"), &gorm.Config{})
|
||||
db, err := gorm.Open(sqlite.Open("test.sqlite"), &gorm.Config{})
|
||||
if err != nil {
|
||||
panic("failed to connect database")
|
||||
}
|
||||
|
||||
// Migrate the schema
|
||||
err = db.AutoMigrate(&internal.User{})
|
||||
err = db.AutoMigrate(&internal.User{}, &internal.ZoneRequest{})
|
||||
if err != nil {
|
||||
panic("failed to run DB migration")
|
||||
}
|
||||
|
|
32
internal/util/fs.go
Normal file
32
internal/util/fs.go
Normal 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
|
||||
}
|
|
@ -1,63 +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 *User `json:"user,omitempty"`
|
||||
RequestID string `json:"id"`
|
||||
}
|
||||
|
||||
// ZoneResponse represents a Zone file request response.
|
||||
type ZoneResponse struct {
|
||||
*Zone
|
||||
|
||||
User *User `json:"user,omitempty"`
|
||||
Elapsed int64 `json:"elapsed"`
|
||||
}
|
||||
|
||||
// Zone struct represents a zonefile.
|
||||
type Zone struct {
|
||||
ID string `json:"id"`
|
||||
UserID string `json:"user_id"` //nolint: tagliatelle
|
||||
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
|
||||
}
|
Loading…
Reference in a new issue