diff --git a/api/domains.go b/api/domains.go
new file mode 100644
index 0000000..288e03e
--- /dev/null
+++ b/api/domains.go
@@ -0,0 +1,209 @@
+package api
+
+import (
+ "encoding/json"
+ "errors"
+ "fmt"
+ "io"
+ "net/http"
+
+ "github.com/julienschmidt/httprouter"
+ "github.com/miekg/dns"
+
+ "git.happydns.org/happydns/config"
+ "git.happydns.org/happydns/model"
+ "git.happydns.org/happydns/storage"
+)
+
+func init() {
+ router.GET("/api/domains", apiAuthHandler(getDomains))
+ router.POST("/api/domains", apiAuthHandler(addDomain))
+ router.DELETE("/api/domains/:domain", apiAuthHandler(domainHandler(delDomain)))
+ router.GET("/api/domains/:domain", apiAuthHandler(domainHandler(getDomain)))
+ router.GET("/api/domains/:domain/rr", apiAuthHandler(domainHandler(axfrDomain)))
+ router.POST("/api/domains/:domain/rr", apiAuthHandler(domainHandler(addRR)))
+ router.DELETE("/api/domains/:domain/rr", apiAuthHandler(domainHandler(delRR)))
+}
+
+func getDomains(_ *config.Options, u *happydns.User, p httprouter.Params, body io.Reader) Response {
+ if domains, err := storage.MainStore.GetDomains(u); err != nil {
+ return APIErrorResponse{
+ err: err,
+ }
+ } else {
+ return APIResponse{
+ response: domains,
+ }
+ }
+}
+
+func addDomain(_ *config.Options, u *happydns.User, p httprouter.Params, body io.Reader) Response {
+ var uz happydns.Domain
+ err := json.NewDecoder(body).Decode(&uz)
+ if err != nil {
+ return APIErrorResponse{
+ err: err,
+ }
+ }
+
+ if len(uz.DomainName) <= 2 {
+ return APIErrorResponse{
+ err: errors.New("The given domain is invalid."),
+ }
+ }
+
+ if uz.DomainName[len(uz.DomainName)-1] != '.' {
+ uz.DomainName = uz.DomainName + "."
+ }
+
+ if storage.MainStore.DomainExists(uz.DomainName) {
+ return APIErrorResponse{
+ err: errors.New("This domain already exists."),
+ }
+ } else if err := storage.MainStore.CreateDomain(u, &uz); err != nil {
+ return APIErrorResponse{
+ err: err,
+ }
+ } else {
+ return APIResponse{
+ response: uz,
+ }
+ }
+}
+
+func delDomain(_ *config.Options, domain *happydns.Domain, body io.Reader) Response {
+ if err := storage.MainStore.DeleteDomain(domain); err != nil {
+ return APIErrorResponse{
+ err: err,
+ }
+ } else {
+ return APIResponse{
+ response: true,
+ }
+ }
+}
+
+func domainHandler(f func(*config.Options, *happydns.Domain, io.Reader) Response) func(*config.Options, *happydns.User, httprouter.Params, io.Reader) Response {
+ return func(opts *config.Options, u *happydns.User, ps httprouter.Params, body io.Reader) Response {
+ if domain, err := storage.MainStore.GetDomainByDN(u, ps.ByName("domain")); err != nil {
+ return APIErrorResponse{
+ status: http.StatusNotFound,
+ err: errors.New("Domain not found"),
+ }
+ } else {
+ return f(opts, domain, body)
+ }
+ }
+}
+
+func getDomain(_ *config.Options, domain *happydns.Domain, body io.Reader) Response {
+ return APIResponse{
+ response: domain,
+ }
+}
+
+func axfrDomain(opts *config.Options, domain *happydns.Domain, body io.Reader) Response {
+ source, err := storage.MainStore.GetSource(&happydns.User{Id: domain.IdUser}, domain.IdSource)
+ if err != nil {
+ return APIErrorResponse{
+ err: err,
+ }
+ }
+
+ rrs, err := source.ImportZone(domain)
+ if err != nil {
+ return APIErrorResponse{
+ err: err,
+ }
+ }
+
+ var ret []map[string]interface{}
+ for _, rr := range rrs {
+ ret = append(ret, map[string]interface{}{
+ "string": rr.String(),
+ "fields": rr,
+ })
+ }
+
+ return APIResponse{
+ response: ret,
+ }
+}
+
+type uploadedRR struct {
+ RR string `json:"string"`
+}
+
+func addRR(opts *config.Options, domain *happydns.Domain, body io.Reader) Response {
+ var urr uploadedRR
+ err := json.NewDecoder(body).Decode(&urr)
+ if err != nil {
+ return APIErrorResponse{
+ err: err,
+ }
+ }
+
+ rr, err := dns.NewRR(fmt.Sprintf("$ORIGIN %s\n$TTL %d\n%s", domain.DomainName, 3600, urr.RR))
+ if err != nil {
+ return APIErrorResponse{
+ err: err,
+ }
+ }
+
+ source, err := storage.MainStore.GetSource(&happydns.User{Id: domain.IdUser}, domain.IdSource)
+ if err != nil {
+ return APIErrorResponse{
+ err: err,
+ }
+ }
+
+ err = source.AddRR(domain, rr)
+ if err != nil {
+ return APIErrorResponse{
+ status: http.StatusInternalServerError,
+ err: err,
+ }
+ }
+
+ return APIResponse{
+ response: map[string]interface{}{
+ "string": rr.String(),
+ },
+ }
+}
+
+func delRR(opts *config.Options, domain *happydns.Domain, body io.Reader) Response {
+ var urr uploadedRR
+ err := json.NewDecoder(body).Decode(&urr)
+ if err != nil {
+ return APIErrorResponse{
+ err: err,
+ }
+ }
+
+ rr, err := dns.NewRR(urr.RR)
+ if err != nil {
+ return APIErrorResponse{
+ err: err,
+ }
+ }
+
+ source, err := storage.MainStore.GetSource(&happydns.User{Id: domain.IdUser}, domain.IdSource)
+ if err != nil {
+ return APIErrorResponse{
+ err: err,
+ }
+ }
+
+ err = source.DeleteRR(domain, rr)
+ if err != nil {
+ return APIErrorResponse{
+ status: http.StatusInternalServerError,
+ err: err,
+ }
+ }
+
+ return APIResponse{
+ response: true,
+ }
+}
diff --git a/api/zones.go b/api/zones.go
deleted file mode 100644
index 3e4a912..0000000
--- a/api/zones.go
+++ /dev/null
@@ -1,264 +0,0 @@
-package api
-
-import (
- "encoding/json"
- "errors"
- "fmt"
- "io"
- "net"
- "net/http"
- "strings"
- "time"
-
- "github.com/julienschmidt/httprouter"
- "github.com/miekg/dns"
-
- "git.happydns.org/happydns/config"
- "git.happydns.org/happydns/model"
- "git.happydns.org/happydns/storage"
-)
-
-func init() {
- router.GET("/api/zones", apiAuthHandler(getZones))
- router.POST("/api/zones", apiAuthHandler(addZone))
- router.DELETE("/api/zones/:zone", apiAuthHandler(zoneHandler(delZone)))
- router.GET("/api/zones/:zone", apiAuthHandler(zoneHandler(getZone)))
- router.GET("/api/zones/:zone/rr", apiAuthHandler(zoneHandler(axfrZone)))
- router.POST("/api/zones/:zone/rr", apiAuthHandler(zoneHandler(addRR)))
- router.DELETE("/api/zones/:zone/rr", apiAuthHandler(zoneHandler(delRR)))
-}
-
-func getZones(_ *config.Options, u *happydns.User, p httprouter.Params, body io.Reader) Response {
- if zones, err := storage.MainStore.GetZones(u); err != nil {
- return APIErrorResponse{
- err: err,
- }
- } else {
- return APIResponse{
- response: zones,
- }
- }
-}
-
-func addZone(_ *config.Options, u *happydns.User, p httprouter.Params, body io.Reader) Response {
- var uz happydns.Zone
- err := json.NewDecoder(body).Decode(&uz)
- if err != nil {
- return APIErrorResponse{
- err: err,
- }
- }
-
- if len(uz.DomainName) <= 2 {
- return APIErrorResponse{
- err: errors.New("The given zone is invalid."),
- }
- }
-
- if uz.DomainName[len(uz.DomainName)-1] != '.' {
- uz.DomainName = uz.DomainName + "."
- }
-
- if len(uz.KeyName) > 1 && uz.KeyName[len(uz.KeyName)-1] != '.' {
- uz.KeyName = uz.KeyName + "."
- }
-
- if storage.MainStore.ZoneExists(uz.DomainName) {
- return APIErrorResponse{
- err: errors.New("This zone already exists."),
- }
- } else if err := storage.MainStore.CreateZone(u, &uz); err != nil {
- return APIErrorResponse{
- err: err,
- }
- } else {
- return APIResponse{
- response: uz,
- }
- }
-}
-
-func delZone(_ *config.Options, zone *happydns.Zone, body io.Reader) Response {
- if err := storage.MainStore.DeleteZone(zone); err != nil {
- return APIErrorResponse{
- err: err,
- }
- } else {
- return APIResponse{
- response: true,
- }
- }
-}
-
-func zoneHandler(f func(*config.Options, *happydns.Zone, io.Reader) Response) func(*config.Options, *happydns.User, httprouter.Params, io.Reader) Response {
- return func(opts *config.Options, u *happydns.User, ps httprouter.Params, body io.Reader) Response {
- if zone, err := storage.MainStore.GetZoneByDN(u, ps.ByName("zone")); err != nil {
- return APIErrorResponse{
- status: http.StatusNotFound,
- err: errors.New("Domain not found"),
- }
- } else {
- return f(opts, zone, body)
- }
- }
-}
-
-func getZone(_ *config.Options, zone *happydns.Zone, body io.Reader) Response {
- return APIResponse{
- response: zone,
- }
-}
-
-func normalizeNSServer(opts *config.Options, srv string) string {
- if srv == "" {
- return opts.DefaultNameServer
- } else if strings.Index(srv, ":") > -1 {
- return srv
- } else {
- return srv + ":53"
- }
-}
-
-func axfrZone(opts *config.Options, zone *happydns.Zone, body io.Reader) Response {
- d := net.Dialer{}
- con, err := d.Dial("tcp", normalizeNSServer(opts, zone.Server))
- if err != nil {
- return APIErrorResponse{
- status: http.StatusInternalServerError,
- err: err,
- }
- }
- defer con.Close()
-
- m := new(dns.Msg)
- m.SetEdns0(4096, true)
- m.SetAxfr(zone.DomainName)
- m.SetTsig(zone.KeyName, zone.KeyAlgo, 300, time.Now().Unix())
-
- dnscon := &dns.Conn{Conn: con}
- transfer := &dns.Transfer{Conn: dnscon, TsigSecret: map[string]string{zone.KeyName: zone.Base64KeyBlob()}}
- c, err := transfer.In(m, normalizeNSServer(opts, zone.Server))
-
- if err != nil {
- return APIErrorResponse{
- status: http.StatusInternalServerError,
- err: err,
- }
- }
-
- var rrs []map[string]interface{}
- for {
- response, ok := <-c
- if !ok {
- break
- }
-
- for _, rr := range response.RR {
- rrs = append(rrs, map[string]interface{}{
- "string": rr.String(),
- "fields": rr,
- })
- }
- }
-
- if len(rrs) > 0 {
- rrs = rrs[0 : len(rrs)-1]
- }
-
- return APIResponse{
- response: rrs,
- }
-}
-
-type uploadedRR struct {
- RR string `json:"string"`
-}
-
-func addRR(opts *config.Options, zone *happydns.Zone, body io.Reader) Response {
- var urr uploadedRR
- err := json.NewDecoder(body).Decode(&urr)
- if err != nil {
- return APIErrorResponse{
- err: err,
- }
- }
-
- 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,
- }
- }
-
- m := new(dns.Msg)
- m.Id = dns.Id()
- m.Opcode = dns.OpcodeUpdate
- m.Question = make([]dns.Question, 1)
- m.Question[0] = dns.Question{zone.DomainName, dns.TypeSOA, dns.ClassINET}
-
- m.Insert([]dns.RR{rr})
-
- c := new(dns.Client)
- c.TsigSecret = map[string]string{zone.KeyName: zone.Base64KeyBlob()}
- m.SetTsig(zone.KeyName, zone.KeyAlgo, 300, time.Now().Unix())
-
- in, rtt, err := c.Exchange(m, normalizeNSServer(opts, zone.Server))
- if err != nil {
- return APIErrorResponse{
- status: http.StatusInternalServerError,
- err: err,
- }
- }
-
- return APIResponse{
- response: map[string]interface{}{
- "in": *in,
- "rtt": rtt,
- "string": rr.String(),
- },
- }
-}
-
-func delRR(opts *config.Options, zone *happydns.Zone, body io.Reader) Response {
- var urr uploadedRR
- err := json.NewDecoder(body).Decode(&urr)
- if err != nil {
- return APIErrorResponse{
- err: err,
- }
- }
-
- rr, err := dns.NewRR(urr.RR)
- if err != nil {
- return APIErrorResponse{
- err: err,
- }
- }
-
- m := new(dns.Msg)
- m.Id = dns.Id()
- m.Opcode = dns.OpcodeUpdate
- m.Question = make([]dns.Question, 1)
- m.Question[0] = dns.Question{zone.DomainName, dns.TypeSOA, dns.ClassINET}
-
- m.Remove([]dns.RR{rr})
-
- c := new(dns.Client)
- c.TsigSecret = map[string]string{zone.KeyName: zone.Base64KeyBlob()}
- m.SetTsig(zone.KeyName, zone.KeyAlgo, 300, time.Now().Unix())
-
- in, rtt, err := c.Exchange(m, normalizeNSServer(opts, zone.Server))
- if err != nil {
- return APIErrorResponse{
- status: http.StatusInternalServerError,
- err: err,
- }
- }
-
- return APIResponse{
- response: map[string]interface{}{
- "in": *in,
- "rtt": rtt,
- },
- }
-}
diff --git a/htdocs/src/router/index.js b/htdocs/src/router/index.js
index 427ec2a..5b4810e 100644
--- a/htdocs/src/router/index.js
+++ b/htdocs/src/router/index.js
@@ -26,39 +26,39 @@ const routes = [
}
},
{
- path: '/zones',
- name: 'zones',
+ path: '/domains',
+ name: 'domains',
component: function () {
- return import(/* webpackChunkName: "zone-list" */ '../views/zone-list.vue')
+ return import(/* webpackChunkName: "domain-list" */ '../views/domain-list.vue')
}
},
{
- path: '/zones/:zone',
+ path: '/domains/:zone',
component: function () {
- return import(/* webpackChunkName: "zone" */ '../views/zone.vue')
+ return import(/* webpackChunkName: "domain" */ '../views/domain.vue')
},
children: [
{
path: '',
- name: 'zone',
+ name: 'domain-source',
component: function () {
- return import(/* webpackChunkName: "zone" */ '../views/zone-details.vue')
+ return import(/* webpackChunkName: "domain-source" */ '../views/domain-source.vue')
}
},
{
path: 'services',
name: 'zone-services',
component: function () {
- return import(/* webpackChunkName: "zone" */ '../views/zone-services.vue')
+ return import(/* webpackChunkName: "zone-services" */ '../views/zone-services.vue')
}
}
]
},
{
- path: '/zones/:zone/records',
+ path: '/zones/:domain/records',
name: 'zone-records',
component: function () {
- return import(/* webpackChunkName: "zone" */ '../views/zone-records.vue')
+ return import(/* webpackChunkName: "zone-records" */ '../views/zone-records.vue')
}
}
]
diff --git a/htdocs/src/views/Index.vue b/htdocs/src/views/Index.vue
index 8910fdf..eb20012 100644
--- a/htdocs/src/views/Index.vue
+++ b/htdocs/src/views/Index.vue
@@ -4,7 +4,7 @@
diff --git a/htdocs/src/views/zone-records.vue b/htdocs/src/views/zone-records.vue
index 1cc443e..0778bb8 100644
--- a/htdocs/src/views/zone-records.vue
+++ b/htdocs/src/views/zone-records.vue
@@ -5,8 +5,8 @@
DNSSEC
-
- {{ zone.domain }}
+
+ {{ domain.domain }}
Resource Records ({{ rrsFiltered.length }}/{{ rrs.length }})
Error: {{ error }}
@@ -74,7 +74,7 @@ export default {
expandrrs: {},
rrs: [],
query: '',
- zone: {}
+ domain: {}
}
},
@@ -94,13 +94,13 @@ export default {
},
mounted () {
- var myzone = this.$route.params.zone
+ var mydomain = this.$route.params.domain
axios
- .get('/api/zones/' + myzone)
- .then(response => (this.zone = response.data))
+ .get('/api/domains/' + mydomain)
+ .then(response => (this.domain = response.data))
axios
- .get('/api/zones/' + myzone + '/rr')
+ .get('/api/domains/' + mydomain + '/rr')
.then(
(response) => (this.rrs = response.data),
(error) => (this.error = error.response.data.errmsg)
@@ -119,24 +119,24 @@ export default {
newRR (idx) {
axios
- .post('/api/zones/' + this.$route.params.zone + '/rr', {
+ .post('/api/domains/' + this.$route.params.domain + '/rr', {
string: this.rrsFiltered[idx].string
})
.then(
(response) => {
axios
- .get('/api/zones/' + this.$route.params.zone + '/rr')
+ .get('/api/domains/' + this.$route.params.domain + '/rr')
.then(response => (this.rrs = response.data))
},
(error) => {
- alert('An error occurs when trying to add RR to zone: ' + error.response.data.errmsg)
+ alert('An error occurs when trying to add RR to the zone: ' + error.response.data.errmsg)
}
)
},
deleteRR (idx) {
axios
- .delete('/api/zones/' + this.$route.params.zone + '/rr', {
+ .delete('/api/domains/' + this.$route.params.domain + '/rr', {
data: {
string: this.rrsFiltered[idx].string
}
@@ -144,11 +144,11 @@ export default {
.then(
(response) => {
axios
- .get('/api/zones/' + this.$route.params.zone + '/rr')
+ .get('/api/domains/' + this.$route.params.domain + '/rr')
.then(response => (this.rrs = response.data))
},
(error) => {
- alert('An error occurs when trying to delete RR in zone: ' + error.response.data.errmsg)
+ alert('An error occurs when trying to delete RR in the zone: ' + error.response.data.errmsg)
}
)
}
diff --git a/htdocs/src/views/zone.vue b/htdocs/src/views/zone.vue
deleted file mode 100644
index 0ca8522..0000000
--- a/htdocs/src/views/zone.vue
+++ /dev/null
@@ -1,74 +0,0 @@
-
-
-
-
-
-
-
-
- {{ zone.domain }}
-
-
-
- Error: {{ error }}
-
-
-
-
-
- My zone
- View services
- View records
- Monitoring
-
-
- Delete my zone
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/model/domain.go b/model/domain.go
new file mode 100644
index 0000000..22c79f9
--- /dev/null
+++ b/model/domain.go
@@ -0,0 +1,34 @@
+package happydns
+
+import (
+ "strings"
+)
+
+type Domain struct {
+ Id int64 `json:"id"`
+ IdUser int64
+ IdSource int64
+ DomainName string `json:"domain"`
+}
+
+type Domains []*Domain
+
+func (d *Domain) NormalizedNSServer() string {
+ if strings.Index(d.DomainName, ":") > -1 {
+ return d.DomainName
+ } else {
+ return d.DomainName + ":53"
+ }
+}
+
+func NewDomain(u *User, s Source, dn string) (d *Domain) {
+ d = &Domain{
+ IdUser: u.Id,
+ //IdSource: s.GetId(),
+ DomainName: dn,
+ }
+
+ d.DomainName = d.NormalizedNSServer()
+
+ return
+}
diff --git a/model/zone.go b/model/zone.go
deleted file mode 100644
index 8bfff3a..0000000
--- a/model/zone.go
+++ /dev/null
@@ -1,34 +0,0 @@
-package happydns
-
-import (
- "encoding/base64"
-)
-
-type Zone struct {
- Id int64 `json:"id"`
- IdUser int64
- DomainName string `json:"domain"`
- Server string `json:"server,omitempty"`
- KeyName string `json:"keyname,omitempty"`
- KeyAlgo string `json:"algorithm,omitempty"`
- KeyBlob []byte `json:"keyblob,omitempty"`
- StorageFacility string `json:"storage_facility,omitempty"`
-}
-
-type Zones []*Zone
-
-func NewZone(u User, dn, server, keyname, algo string, keyblob []byte, storage string) *Zone {
- return &Zone{
- IdUser: u.Id,
- DomainName: dn,
- Server: server,
- KeyName: keyname,
- KeyAlgo: algo,
- KeyBlob: keyblob,
- StorageFacility: storage,
- }
-}
-
-func (z *Zone) Base64KeyBlob() string {
- return base64.StdEncoding.EncodeToString(z.KeyBlob)
-}
diff --git a/static.go b/static.go
index 0d70ce4..f696c19 100644
--- a/static.go
+++ b/static.go
@@ -33,6 +33,20 @@ func init() {
fwd_request(w, r, opts.DevProxy)
}
})
+ api.Router().GET("/domains/*_", func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
+ opts := r.Context().Value("opts").(*config.Options)
+
+ if opts.DevProxy == "" {
+ if data, err := Asset("htdocs/dist/index.html"); err != nil {
+ fmt.Fprintf(w, "{\"errmsg\":%q}", err)
+ } else {
+ w.Write(data)
+ }
+ } else {
+ r.URL.Path = "/"
+ fwd_request(w, r, opts.DevProxy)
+ }
+ })
api.Router().GET("/join", func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
opts := r.Context().Value("opts").(*config.Options)
diff --git a/storage/interface.go b/storage/interface.go
index 374eb6c..70ddbe4 100644
--- a/storage/interface.go
+++ b/storage/interface.go
@@ -8,6 +8,16 @@ type Storage interface {
DoMigration() error
Close() error
+ GetDomains(u *happydns.User) (happydns.Domains, error)
+ GetDomain(u *happydns.User, id int) (*happydns.Domain, error)
+ GetDomainByDN(u *happydns.User, dn string) (*happydns.Domain, error)
+ DomainExists(dn string) bool
+ CreateDomain(u *happydns.User, z *happydns.Domain) error
+ UpdateDomain(z *happydns.Domain) error
+ UpdateDomainOwner(z *happydns.Domain, newOwner *happydns.User) error
+ DeleteDomain(z *happydns.Domain) error
+ ClearDomains() error
+
GetSession(id []byte) (*happydns.Session, error)
CreateSession(session *happydns.Session) error
UpdateSession(session *happydns.Session) error
@@ -22,14 +32,4 @@ type Storage interface {
UpdateUser(user *happydns.User) error
DeleteUser(user *happydns.User) error
ClearUsers() error
-
- GetZones(u *happydns.User) (happydns.Zones, error)
- GetZone(u *happydns.User, id int) (*happydns.Zone, error)
- GetZoneByDN(u *happydns.User, dn string) (*happydns.Zone, error)
- ZoneExists(dn string) bool
- CreateZone(u *happydns.User, z *happydns.Zone) error
- UpdateZone(z *happydns.Zone) error
- UpdateZoneOwner(z *happydns.Zone, newOwner *happydns.User) error
- DeleteZone(z *happydns.Zone) error
- ClearZones() error
}
diff --git a/storage/leveldb/domain.go b/storage/leveldb/domain.go
new file mode 100644
index 0000000..1e653c6
--- /dev/null
+++ b/storage/leveldb/domain.go
@@ -0,0 +1,127 @@
+package database
+
+import (
+ "fmt"
+
+ "git.happydns.org/happydns/model"
+
+ "github.com/syndtr/goleveldb/leveldb"
+ "github.com/syndtr/goleveldb/leveldb/util"
+)
+
+func (s *LevelDBStorage) GetDomains(u *happydns.User) (domains happydns.Domains, err error) {
+ iter := s.search("domain-")
+ defer iter.Release()
+
+ for iter.Next() {
+ var z happydns.Domain
+
+ err = decodeData(iter.Value(), &z)
+ if err != nil {
+ return
+ }
+
+ if z.IdUser == u.Id {
+ domains = append(domains, &z)
+ }
+ }
+
+ return
+}
+
+func (s *LevelDBStorage) GetDomain(u *happydns.User, id int) (z *happydns.Domain, err error) {
+ z = &happydns.Domain{}
+ err = s.get(fmt.Sprintf("domain-%d", id), &z)
+
+ if z.IdUser != u.Id {
+ z = nil
+ err = leveldb.ErrNotFound
+ }
+
+ return
+}
+
+func (s *LevelDBStorage) GetDomainByDN(u *happydns.User, dn string) (*happydns.Domain, error) {
+ domains, err := s.GetDomains(u)
+ if err != nil {
+ return nil, err
+ }
+
+ for _, domain := range domains {
+ if domain.DomainName == dn {
+ return domain, nil
+ }
+ }
+
+ return nil, leveldb.ErrNotFound
+}
+
+func (s *LevelDBStorage) DomainExists(dn string) bool {
+ iter := s.search("domain-")
+ defer iter.Release()
+
+ for iter.Next() {
+ var z happydns.Domain
+
+ err := decodeData(iter.Value(), &z)
+ if err != nil {
+ continue
+ }
+
+ if z.DomainName == dn {
+ return true
+ }
+ }
+
+ return false
+}
+
+func (s *LevelDBStorage) CreateDomain(u *happydns.User, z *happydns.Domain) error {
+ key, id, err := s.findInt63Key("domain-")
+ if err != nil {
+ return err
+ }
+
+ z.Id = id
+ z.IdUser = u.Id
+ return s.put(key, z)
+}
+
+func (s *LevelDBStorage) UpdateDomain(z *happydns.Domain) error {
+ return s.put(fmt.Sprintf("domain-%d", z.Id), z)
+}
+
+func (s *LevelDBStorage) UpdateDomainOwner(z *happydns.Domain, newOwner *happydns.User) error {
+ z.IdUser = newOwner.Id
+ return s.put(fmt.Sprintf("domain-%d", z.Id), z)
+}
+
+func (s *LevelDBStorage) DeleteDomain(z *happydns.Domain) error {
+ return s.delete(fmt.Sprintf("domain-%d", z.Id))
+}
+
+func (s *LevelDBStorage) ClearDomains() error {
+ tx, err := s.db.OpenTransaction()
+ if err != nil {
+ return err
+ }
+
+ iter := tx.NewIterator(util.BytesPrefix([]byte("domain-")), nil)
+ defer iter.Release()
+
+ for iter.Next() {
+ err = tx.Delete(iter.Key(), nil)
+ if err != nil {
+ tx.Discard()
+ return err
+ }
+ }
+
+ err = tx.Commit()
+ if err != nil {
+ tx.Discard()
+ return err
+ }
+
+ return nil
+}
diff --git a/storage/leveldb/zone.go b/storage/leveldb/zone.go
deleted file mode 100644
index 00413ab..0000000
--- a/storage/leveldb/zone.go
+++ /dev/null
@@ -1,127 +0,0 @@
-package database
-
-import (
- "fmt"
-
- "git.happydns.org/happydns/model"
-
- "github.com/syndtr/goleveldb/leveldb"
- "github.com/syndtr/goleveldb/leveldb/util"
-)
-
-func (s *LevelDBStorage) GetZones(u *happydns.User) (zones happydns.Zones, err error) {
- iter := s.search("zone-")
- defer iter.Release()
-
- for iter.Next() {
- var z happydns.Zone
-
- err = decodeData(iter.Value(), &z)
- if err != nil {
- return
- }
-
- if z.IdUser == u.Id {
- zones = append(zones, &z)
- }
- }
-
- return
-}
-
-func (s *LevelDBStorage) GetZone(u *happydns.User, id int) (z *happydns.Zone, err error) {
- z = &happydns.Zone{}
- err = s.get(fmt.Sprintf("zone-%d", id), &z)
-
- if z.IdUser != u.Id {
- z = nil
- err = leveldb.ErrNotFound
- }
-
- return
-}
-
-func (s *LevelDBStorage) GetZoneByDN(u *happydns.User, dn string) (*happydns.Zone, error) {
- zones, err := s.GetZones(u)
- if err != nil {
- return nil, err
- }
-
- for _, zone := range zones {
- if zone.DomainName == dn {
- return zone, nil
- }
- }
-
- return nil, leveldb.ErrNotFound
-}
-
-func (s *LevelDBStorage) ZoneExists(dn string) bool {
- iter := s.search("zone-")
- defer iter.Release()
-
- for iter.Next() {
- var z happydns.Zone
-
- err := decodeData(iter.Value(), &z)
- if err != nil {
- continue
- }
-
- if z.DomainName == dn {
- return true
- }
- }
-
- return false
-}
-
-func (s *LevelDBStorage) CreateZone(u *happydns.User, z *happydns.Zone) error {
- key, id, err := s.findInt63Key("zone-")
- if err != nil {
- return err
- }
-
- z.Id = id
- z.IdUser = u.Id
- return s.put(key, z)
-}
-
-func (s *LevelDBStorage) UpdateZone(z *happydns.Zone) error {
- return s.put(fmt.Sprintf("zone-%d", z.Id), z)
-}
-
-func (s *LevelDBStorage) UpdateZoneOwner(z *happydns.Zone, newOwner *happydns.User) error {
- z.IdUser = newOwner.Id
- return s.put(fmt.Sprintf("zone-%d", z.Id), z)
-}
-
-func (s *LevelDBStorage) DeleteZone(z *happydns.Zone) error {
- return s.delete(fmt.Sprintf("zone-%d", z.Id))
-}
-
-func (s *LevelDBStorage) ClearZones() error {
- tx, err := s.db.OpenTransaction()
- if err != nil {
- return err
- }
-
- iter := tx.NewIterator(util.BytesPrefix([]byte("zone-")), nil)
- defer iter.Release()
-
- for iter.Next() {
- err = tx.Delete(iter.Key(), nil)
- if err != nil {
- tx.Discard()
- return err
- }
- }
-
- err = tx.Commit()
- if err != nil {
- tx.Discard()
- return err
- }
-
- return nil
-}
diff --git a/storage/mysql/domain.go b/storage/mysql/domain.go
new file mode 100644
index 0000000..b23325b
--- /dev/null
+++ b/storage/mysql/domain.go
@@ -0,0 +1,81 @@
+package database
+
+import (
+ "git.happydns.org/happydns/model"
+)
+
+func (s *MySQLStorage) GetDomains(u *happydns.User) (domains happydns.Domains, err error) {
+ if rows, errr := s.db.Query("SELECT id_domain, id_user, id_source, domain FROM domains WHERE id_user = ?", u.Id); errr != nil {
+ return nil, errr
+ } else {
+ defer rows.Close()
+
+ for rows.Next() {
+ var z happydns.Domain
+ if err = rows.Scan(&z.Id, &z.IdUser, &z.IdSource, &z.DomainName); err != nil {
+ return
+ }
+ domains = append(domains, &z)
+ }
+ if err = rows.Err(); err != nil {
+ return
+ }
+
+ return
+ }
+}
+
+func (s *MySQLStorage) GetDomain(u *happydns.User, id int) (z *happydns.Domain, err error) {
+ z = &happydns.Domain{}
+ err = s.db.QueryRow("SELECT id_domain, id_user, id_source, domain FROM domains WHERE id_domain=? AND id_user=?", id, u.Id).Scan(&z.Id, &z.IdUser, &z.IdSource, &z.DomainName)
+ return
+}
+
+func (s *MySQLStorage) GetDomainByDN(u *happydns.User, dn string) (z *happydns.Domain, err error) {
+ z = &happydns.Domain{}
+ err = s.db.QueryRow("SELECT id_domain, id_user, id_source, domain FROM domains WHERE domain=? AND id_user=?", dn, u.Id).Scan(&z.Id, &z.IdUser, &z.IdSource, &z.DomainName)
+ return
+}
+
+func (s *MySQLStorage) DomainExists(dn string) bool {
+ var z int
+ err := s.db.QueryRow("SELECT 1 FROM domains WHERE domain=?", dn).Scan(&z)
+ return err == nil && z == 1
+}
+
+func (s *MySQLStorage) CreateDomain(u *happydns.User, src happydns.SourceType, z *happydns.Domain) error {
+ if res, err := s.db.Exec("INSERT INTO domains (id_user, id_source, domain) VALUES (?, ?, ?)", u.Id, src.Id, z.DomainName); err != nil {
+ return err
+ } else if z.Id, err = res.LastInsertId(); err != nil {
+ return err
+ } else {
+ return nil
+ }
+}
+
+func (s *MySQLStorage) UpdateDomain(z *happydns.Domain) error {
+ if _, err := s.db.Exec("UPDATE domains SET id_source = ?, domain = ? WHERE id_domain = ?", z.IdSource, z.DomainName, z.Id); err != nil {
+ return err
+ } else {
+ return nil
+ }
+}
+
+func (s *MySQLStorage) UpdateDomainOwner(z *happydns.Domain, newOwner *happydns.User) error {
+ if _, err := s.db.Exec("UPDATE domains SET id_user = ? WHERE id_domain = ?", newOwner.Id, z.Id); err != nil {
+ return err
+ } else {
+ z.IdUser = newOwner.Id
+ return nil
+ }
+}
+
+func (s *MySQLStorage) DeleteDomain(z *happydns.Domain) error {
+ _, err := s.db.Exec("DELETE FROM domains WHERE id_domain = ?", z.Id)
+ return err
+}
+
+func (s *MySQLStorage) ClearDomains() error {
+ _, err := s.db.Exec("DELETE FROM domains")
+ return err
+}
diff --git a/storage/mysql/schemas.go b/storage/mysql/schemas.go
index 70c2fe4..724cc0b 100644
--- a/storage/mysql/schemas.go
+++ b/storage/mysql/schemas.go
@@ -2,7 +2,7 @@
package database // import "happydns.org/database"
-const schemaVersion = 2
+const schemaVersion = 3
var schemaRevisions = map[uint16]string{
1: `CREATE TABLE schema_version (
@@ -50,5 +50,18 @@ ALTER TABLE user_sessions
ALTER TABLE zones
CHANGE id_user id_user BIGINT NOT NULL;
+`,
+ 3: `ALTER TABLE zones
+ DROP COLUMN server;
+ALTER TABLE zones
+ DROP COLUMN key_name;
+ALTER TABLE zones
+ DROP COLUMN key_algo;
+ALTER TABLE zones
+ DROP COLUMN key_blob;
+ALTER TABLE zones
+ DROP COLUMN storage_facility;
+
+RENAME TABLE zones TO domains;
`,
}
diff --git a/storage/mysql/schemas/003.sql b/storage/mysql/schemas/003.sql
new file mode 100644
index 0000000..70f7195
--- /dev/null
+++ b/storage/mysql/schemas/003.sql
@@ -0,0 +1,12 @@
+ALTER TABLE zones
+ DROP COLUMN server;
+ALTER TABLE zones
+ DROP COLUMN key_name;
+ALTER TABLE zones
+ DROP COLUMN key_algo;
+ALTER TABLE zones
+ DROP COLUMN key_blob;
+ALTER TABLE zones
+ DROP COLUMN storage_facility;
+
+RENAME TABLE zones TO domains;
diff --git a/storage/mysql/zone.go b/storage/mysql/zone.go
deleted file mode 100644
index c6ddff7..0000000
--- a/storage/mysql/zone.go
+++ /dev/null
@@ -1,81 +0,0 @@
-package database
-
-import (
- "git.happydns.org/happydns/model"
-)
-
-func (s *MySQLStorage) GetZones(u *happydns.User) (zones happydns.Zones, err error) {
- if rows, errr := s.db.Query("SELECT id_zone, id_user, domain, server, key_name, key_algo, key_blob, storage_facility FROM zones WHERE id_user = ?", u.Id); errr != nil {
- return nil, errr
- } else {
- defer rows.Close()
-
- for rows.Next() {
- var z happydns.Zone
- if err = rows.Scan(&z.Id, &z.IdUser, &z.DomainName, &z.Server, &z.KeyName, &z.KeyAlgo, &z.KeyBlob, &z.StorageFacility); err != nil {
- return
- }
- zones = append(zones, &z)
- }
- if err = rows.Err(); err != nil {
- return
- }
-
- return
- }
-}
-
-func (s *MySQLStorage) GetZone(u *happydns.User, id int) (z *happydns.Zone, err error) {
- z = &happydns.Zone{}
- err = s.db.QueryRow("SELECT id_zone, id_user, domain, server, key_name, key_algo, key_blob, storage_facility FROM zones WHERE id_zone=? AND id_user=?", id, u.Id).Scan(&z.Id, &z.IdUser, &z.DomainName, &z.Server, &z.KeyName, &z.KeyAlgo, &z.KeyBlob, &z.StorageFacility)
- return
-}
-
-func (s *MySQLStorage) GetZoneByDN(u *happydns.User, dn string) (z *happydns.Zone, err error) {
- z = &happydns.Zone{}
- err = s.db.QueryRow("SELECT id_zone, id_user, domain, server, key_name, key_algo, key_blob, storage_facility FROM zones WHERE domain=? AND id_user=?", dn, u.Id).Scan(&z.Id, &z.IdUser, &z.DomainName, &z.Server, &z.KeyName, &z.KeyAlgo, &z.KeyBlob, &z.StorageFacility)
- return
-}
-
-func (s *MySQLStorage) ZoneExists(dn string) bool {
- var z int
- err := s.db.QueryRow("SELECT 1 FROM zones WHERE domain=?", dn).Scan(&z)
- return err == nil && z == 1
-}
-
-func (s *MySQLStorage) CreateZone(u *happydns.User, z *happydns.Zone) error {
- if res, err := s.db.Exec("INSERT INTO zones (id_user, domain, server, key_name, key_blob, storage_facility) VALUES (?, ?, ?, ?, ?, ?)", u.Id, z.DomainName, z.Server, z.KeyName, z.KeyBlob, z.StorageFacility); err != nil {
- return err
- } else if z.Id, err = res.LastInsertId(); err != nil {
- return err
- } else {
- return nil
- }
-}
-
-func (s *MySQLStorage) UpdateZone(z *happydns.Zone) error {
- if _, err := s.db.Exec("UPDATE zones SET domain = ?, key_name = ?, key_algo = ?, key_blob = ?, storage_facility = ? WHERE id_zone = ?", z.DomainName, z.KeyName, z.KeyAlgo, z.KeyBlob, z.StorageFacility, z.Id); err != nil {
- return err
- } else {
- return nil
- }
-}
-
-func (s *MySQLStorage) UpdateZoneOwner(z *happydns.Zone, newOwner *happydns.User) error {
- if _, err := s.db.Exec("UPDATE zones SET id_user = ? WHERE id_zone = ?", newOwner.Id, z.Id); err != nil {
- return err
- } else {
- z.IdUser = newOwner.Id
- return nil
- }
-}
-
-func (s *MySQLStorage) DeleteZone(z *happydns.Zone) error {
- _, err := s.db.Exec("DELETE FROM zones WHERE id_zone = ?", z.Id)
- return err
-}
-
-func (s *MySQLStorage) ClearZones() error {
- _, err := s.db.Exec("DELETE FROM zones")
- return err
-}