mirror of
https://git.freecumextremist.com/grumbulon/pomme.git
synced 2024-11-22 15:33:45 +00:00
161 lines
3.4 KiB
Go
161 lines
3.4 KiB
Go
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 {
|
|
http.Error(w, "request body too large", http.StatusRequestEntityTooLarge)
|
|
|
|
return
|
|
}
|
|
|
|
defer file.Close() //nolint: errcheck
|
|
|
|
name := strings.Split(header.Filename, ".")
|
|
|
|
if _, err = io.Copy(&buf, file); err != nil {
|
|
http.Error(w, "internal server error", http.StatusInternalServerError)
|
|
|
|
return
|
|
}
|
|
|
|
if err = util.MakeLocal(name[0], claims["username"].(string), buf); err != nil {
|
|
http.Error(w, "internal server error", http.StatusInternalServerError)
|
|
|
|
return
|
|
}
|
|
|
|
db, ok := r.Context().Value(keyPrincipalContextID).(*gorm.DB)
|
|
if !ok {
|
|
http.Error(w, "internal server error", http.StatusInternalServerError)
|
|
|
|
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 {
|
|
http.Error(w, "Unable to parse request", http.StatusInternalServerError)
|
|
|
|
return
|
|
}
|
|
|
|
filename := r.Form.Get("filename")
|
|
|
|
if filename == "" {
|
|
http.Error(w, "No filename parsed", http.StatusInternalServerError)
|
|
|
|
return
|
|
}
|
|
|
|
db, ok := r.Context().Value(keyPrincipalContextID).(*gorm.DB)
|
|
if !ok {
|
|
http.Error(w, "internal server error", http.StatusInternalServerError)
|
|
|
|
return
|
|
}
|
|
|
|
db.Where(ZoneRequest{
|
|
Zone: &Zone{
|
|
RawFileName: filename,
|
|
},
|
|
User: claims["username"].(string),
|
|
}).First(&result)
|
|
|
|
if result == (internal.ZoneRequest{}) {
|
|
http.Error(w, "Internal server error", http.StatusInternalServerError)
|
|
|
|
return
|
|
}
|
|
|
|
zoneFile := newZoneRequest(result.RawFileName, claims["username"].(string))
|
|
|
|
if err := zoneFile.Parse(); err != nil {
|
|
http.Error(w, "Unable to parse zonefile", http.StatusInternalServerError)
|
|
|
|
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
|
|
}
|