Save zones into DB

This commit is contained in:
nemunaire 2019-09-09 19:21:24 +02:00
parent a5e7f79b18
commit 0b55b5fed3
5 changed files with 164 additions and 75 deletions

View File

@ -10,6 +10,8 @@ import (
"github.com/julienschmidt/httprouter"
"github.com/miekg/dns"
"git.nemunai.re/libredns/struct"
)
func init() {
@ -22,29 +24,20 @@ func init() {
router.DELETE("/api/zones/:zone/rr", apiHandler(zoneHandler(delRR)))
}
var tmpZones = []string{}
func getZones(p httprouter.Params, body io.Reader) Response {
return APIResponse{
response: tmpZones,
}
}
func existsZone(zone string) bool {
for _, z := range tmpZones {
if z == zone {
return true
if zones, err := libredns.GetZones(); err != nil {
return APIErrorResponse{
err: err,
}
} else {
return APIResponse{
response: zones,
}
}
return false
}
type uploadedZone struct {
Zone string `json:"domainName"`
}
func addZone(p httprouter.Params, body io.Reader) Response {
var uz uploadedZone
var uz libredns.Zone
err := json.NewDecoder(body).Decode(&uz)
if err != nil {
return APIErrorResponse{
@ -52,72 +45,69 @@ func addZone(p httprouter.Params, body io.Reader) Response {
}
}
if uz.Zone[len(uz.Zone)-1] != '.' {
uz.Zone = uz.Zone + "."
if len(uz.DomainName) <= 2 {
return APIErrorResponse{
err: errors.New("The given zone is invalid."),
}
}
if existsZone(uz.Zone) {
if uz.DomainName[len(uz.DomainName)-1] != '.' {
uz.DomainName = uz.DomainName + "."
}
if libredns.ZoneExists(uz.DomainName) {
return APIErrorResponse{
err: errors.New("This zone already exists."),
}
} else {
tmpZones = append(tmpZones, uz.Zone)
return getZone(uz.Zone, body)
}
}
func delZone(zone string, body io.Reader) Response {
index := -1
for i := range tmpZones {
if tmpZones[i] == zone {
index = i
break
}
}
if index == -1 {
} else if zone, err := uz.NewZone(); err != nil {
return APIErrorResponse{
err: errors.New("This zone doesn't exist."),
err: err,
}
} else {
return APIResponse{
response: zone,
}
}
tmpZones = append(tmpZones[:index], tmpZones[index+1:]...)
return APIResponse{
response: true,
}
}
func zoneHandler(f func(string, io.Reader) Response) func(httprouter.Params, io.Reader) Response {
return func(ps httprouter.Params, body io.Reader) Response {
zone := ps.ByName("zone")
func delZone(zone libredns.Zone, body io.Reader) Response {
if _, err := zone.Delete(); err != nil {
return APIErrorResponse{
err: err,
}
} else {
return APIResponse{
response: true,
}
}
}
if !existsZone(zone) {
func zoneHandler(f func(libredns.Zone, io.Reader) Response) func(httprouter.Params, io.Reader) Response {
return func(ps httprouter.Params, body io.Reader) Response {
if zone, err := libredns.GetZoneByDN(ps.ByName("zone")); err != nil {
return APIErrorResponse{
status: http.StatusNotFound,
err: errors.New("Domain not found"),
}
} else {
return f(zone, body)
}
return f(zone, body)
}
}
func getZone(zone string, body io.Reader) Response {
func getZone(zone libredns.Zone, body io.Reader) Response {
return APIResponse{
response: map[string]interface{}{
"dn": zone,
},
response: zone,
}
}
func axfrZone(zone string, body io.Reader) Response {
func axfrZone(zone libredns.Zone, body io.Reader) Response {
t := new(dns.Transfer)
m := new(dns.Msg)
m.SetEdns0(4096, true)
t.TsigSecret = map[string]string{"ddns.": "so6ZGir4GPAqINNh9U5c3A=="}
m.SetAxfr(zone)
m.SetAxfr(zone.DomainName)
m.SetTsig("ddns.", dns.HmacSHA256, 300, time.Now().Unix())
c, err := t.In(m, DefaultNameServer)
@ -151,7 +141,7 @@ type uploadedRR struct {
RR string `json:"string"`
}
func addRR(zone string, body io.Reader) Response {
func addRR(zone libredns.Zone, body io.Reader) Response {
var urr uploadedRR
err := json.NewDecoder(body).Decode(&urr)
if err != nil {
@ -160,7 +150,7 @@ func addRR(zone string, body io.Reader) Response {
}
}
rr, err := dns.NewRR(fmt.Sprintf("$ORIGIN %s\n$TTL %d\n%s", zone, 3600, urr.RR))
rr, err := dns.NewRR(fmt.Sprintf("$ORIGIN %s\n$TTL %d\n%s", zone.DomainName, 3600, urr.RR))
if err != nil {
return APIErrorResponse{
err: err,
@ -171,7 +161,7 @@ func addRR(zone string, body io.Reader) Response {
m.Id = dns.Id()
m.Opcode = dns.OpcodeUpdate
m.Question = make([]dns.Question, 1)
m.Question[0] = dns.Question{zone, dns.TypeSOA, dns.ClassINET}
m.Question[0] = dns.Question{zone.DomainName, dns.TypeSOA, dns.ClassINET}
m.Insert([]dns.RR{rr})
@ -196,7 +186,7 @@ func addRR(zone string, body io.Reader) Response {
}
}
func delRR(zone string, body io.Reader) Response {
func delRR(zone libredns.Zone, body io.Reader) Response {
var urr uploadedRR
err := json.NewDecoder(body).Decode(&urr)
if err != nil {
@ -216,7 +206,7 @@ func delRR(zone string, body io.Reader) Response {
m.Id = dns.Id()
m.Opcode = dns.OpcodeUpdate
m.Question = make([]dns.Question, 1)
m.Question[0] = dns.Question{zone, dns.TypeSOA, dns.ClassINET}
m.Question[0] = dns.Question{zone.DomainName, dns.TypeSOA, dns.ClassINET}
m.Remove([]dns.RR{rr})

View File

@ -17,7 +17,7 @@
<tbody>
<tr v-for="(zone, index) in zones" v-bind:key="index">
<td @click="show(zone)" class="text-monospace">
{{ zone }}
{{ zone.domain }}
</td>
<td>
<button type="button" @click="show(zone)" class="btn btn-sm btn-primary"><span class="glyphicon glyphicon-search" aria-hidden="true"></span></button>
@ -80,14 +80,22 @@ export default {
attachZone (dn) {
axios
.post('/api/zones', {
domainName: this.toAttachDN
domain: this.toAttachDN
})
.then(response => (this.zones.push(response.data.dn)))
.then(
(response) => {
if (this.zones == null) this.zones = []
this.zones.push(response.data)
},
(error) => {
alert('Unable to attach the given zone: ' + error.response.data.errmsg)
}
)
},
deleteZone (dn) {
deleteZone (zone) {
axios
.delete('/api/zones/' + dn)
.delete('/api/zones/' + zone.domain)
.then(response => (
axios
.get('/api/zones')
@ -95,8 +103,8 @@ export default {
))
},
show (dn) {
this.$router.push('/zones/' + dn)
show (zone) {
this.$router.push('/zones/' + zone.domain)
},
modalShown () {

View File

@ -9,6 +9,7 @@ import (
"strings"
"git.nemunai.re/libredns/api"
"git.nemunai.re/libredns/struct"
)
type ResponseWriterPrefix struct {
@ -55,7 +56,7 @@ func main() {
// Read parameters from command line
flag.StringVar(&DevProxy, "dev", DevProxy, "Proxify traffic to this host for static assets")
var bind = flag.String("bind", ":8081", "Bind port/socket")
var dsn = flag.String("dsn", DSNGenerator(), "DSN to connect to the MySQL server")
var dsn = flag.String("dsn", libredns.DSNGenerator(), "DSN to connect to the MySQL server")
var baseURL = flag.String("baseurl", "/", "URL prepended to each URL")
flag.StringVar(&api.DefaultNameServer, "defaultns", api.DefaultNameServer, "Adress to the default name server")
flag.Parse()
@ -71,13 +72,13 @@ func main() {
// Initialize contents
log.Println("Opening database...")
if err := DBInit(*dsn); err != nil {
if err := libredns.DBInit(*dsn); err != nil {
log.Fatal("Cannot open the database: ", err)
}
defer DBClose()
defer libredns.DBClose()
log.Println("Creating database...")
if err := DBCreate(); err != nil {
if err := libredns.DBCreate(); err != nil {
log.Fatal("Cannot create database: ", err)
}

View File

@ -1,4 +1,4 @@
package main
package libredns
import (
"database/sql"
@ -59,9 +59,10 @@ func DBCreate() error {
if _, err := db.Exec(`
CREATE TABLE IF NOT EXISTS users(
id_user INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(255) NOT NULL,
email VARCHAR(255) NOT NULL UNIQUE,
password BINARY(64) NOT NULL,
email VARCHAR(255) NOT NULL
salt BINARY(8) NOT NULL,
registration_time TIMESTAMP NOT NULL
) DEFAULT CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci;
`); err != nil {
return err

89
struct/zone.go Normal file
View File

@ -0,0 +1,89 @@
package libredns
import (
)
type Zone struct {
Id int64 `json:"id"`
DomainName string `json:"domain"`
Server string `json:"server,omitempty"`
KeyName string `json:"keyname,omitempty"`
KeyBlob []byte `json:"keyblob,omitempty"`
}
func GetZones() (zones []Zone, err error) {
if rows, errr := DBQuery("SELECT id_zone, domain, server, key_name, key_blob FROM zones"); errr != nil {
return nil, errr
} else {
defer rows.Close()
for rows.Next() {
var z Zone
if err = rows.Scan(&z.Id, &z.DomainName, &z.Server, &z.KeyName, &z.KeyBlob); err != nil {
return
}
zones = append(zones, z)
}
if err = rows.Err(); err != nil {
return
}
return
}
}
func GetZone(id int) (z Zone, err error) {
err = DBQueryRow("SELECT id_user, domain, server, key_name, key_blob FROM zones WHERE id_zone=?", id).Scan(&z.Id, &z.DomainName, &z.Server, &z.KeyName, &z.KeyBlob)
return
}
func GetZoneByDN(dn string) (z Zone, err error) {
err = DBQueryRow("SELECT id_zone, domain, server, key_name, key_blob FROM zones WHERE domain=?", dn).Scan(&z.Id, &z.DomainName, &z.Server, &z.KeyName, &z.KeyBlob)
return
}
func ZoneExists(dn string) bool {
var z int
err := DBQueryRow("SELECT 1 FROM zones WHERE domain=?", dn).Scan(&z)
return err == nil && z == 1
}
func (z *Zone) NewZone() (Zone, error) {
if res, err := DBExec("INSERT INTO zones (domain, server, key_name, key_blob) VALUES (?, ?, ?, ?)", z.DomainName, z.Server, z.KeyName, z.KeyBlob); err != nil {
return *z, err
} else if z.Id, err = res.LastInsertId(); err != nil {
return *z, err
} else {
return *z, nil
}
}
func (z *Zone) Update() (int64, error) {
if res, err := DBExec("UPDATE zones SET domain = ? WHERE id_zone = ?", z.DomainName, z.Id); err != nil {
return 0, err
} else if nb, err := res.RowsAffected(); err != nil {
return 0, err
} else {
return nb, err
}
}
func (z *Zone) Delete() (int64, error) {
if res, err := DBExec("DELETE FROM zones WHERE id_zone = ?", z.Id); err != nil {
return 0, err
} else if nb, err := res.RowsAffected(); err != nil {
return 0, err
} else {
return nb, err
}
}
func ClearZones() (int64, error) {
if res, err := DBExec("DELETE FROM zones"); err != nil {
return 0, err
} else if nb, err := res.RowsAffected(); err != nil {
return 0, err
} else {
return nb, err
}
}