Use identifiers globally

This commit is contained in:
nemunaire 2022-10-25 18:16:34 +02:00
parent 5e65e727ad
commit c29a8fa57f
28 changed files with 202 additions and 128 deletions

View File

@ -35,7 +35,6 @@ import (
"bytes" "bytes"
"fmt" "fmt"
"net/http" "net/http"
"strconv"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
@ -96,7 +95,7 @@ func newDomain(c *gin.Context) {
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": fmt.Sprintf("Something is wrong in received data: %s", err.Error())}) c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": fmt.Sprintf("Something is wrong in received data: %s", err.Error())})
return return
} }
ud.Id = 0 ud.Id = nil
ud.IdUser = user.Id ud.IdUser = user.Id
ApiResponse(c, ud, storage.MainStore.CreateDomain(user, ud)) ApiResponse(c, ud, storage.MainStore.CreateDomain(user, ud))
@ -126,7 +125,7 @@ func updateUserDomain(c *gin.Context) {
func deleteUserDomain(c *gin.Context) { func deleteUserDomain(c *gin.Context) {
user := c.MustGet("user").(*happydns.User) user := c.MustGet("user").(*happydns.User)
domainid, err := strconv.ParseInt(c.Param("domain"), 10, 64) domainid, err := happydns.NewIdentifierFromString(c.Param("domain"))
if err != nil { if err != nil {
domain, err := storage.MainStore.GetDomainByDN(user, c.Param("domain")) domain, err := storage.MainStore.GetDomainByDN(user, c.Param("domain"))
if err != nil { if err != nil {

View File

@ -136,7 +136,7 @@ func newUserProvider(c *gin.Context) {
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": fmt.Sprintf("Something is wrong in received data: %s", err.Error())}) c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": fmt.Sprintf("Something is wrong in received data: %s", err.Error())})
return return
} }
us.Id = 0 us.Id = nil
src, err := storage.MainStore.CreateProvider(user.(*happydns.User), us, "") src, err := storage.MainStore.CreateProvider(user.(*happydns.User), us, "")
ApiResponse(c, src, err) ApiResponse(c, src, err)

View File

@ -35,7 +35,6 @@ import (
"encoding/base64" "encoding/base64"
"fmt" "fmt"
"net/http" "net/http"
"strconv"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
@ -88,7 +87,7 @@ func newUserDomainZone(c *gin.Context) {
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": fmt.Sprintf("Something is wrong in received data: %s", err.Error())}) c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": fmt.Sprintf("Something is wrong in received data: %s", err.Error())})
return return
} }
uz.Id = 0 uz.Id = nil
ApiResponse(c, uz, storage.MainStore.CreateZone(uz)) ApiResponse(c, uz, storage.MainStore.CreateZone(uz))
} }
@ -167,7 +166,7 @@ func patchZoneService(c *gin.Context) {
} }
func deleteZone(c *gin.Context) { func deleteZone(c *gin.Context) {
zoneid, err := strconv.ParseInt(c.Param("zoneid"), 10, 64) zoneid, err := happydns.NewIdentifierFromString(c.Param("zoneid"))
if err != nil { if err != nil {
c.AbortWithStatusJSON(http.StatusNotFound, gin.H{"errmsg": err.Error()}) c.AbortWithStatusJSON(http.StatusNotFound, gin.H{"errmsg": err.Error()})
} else { } else {

View File

@ -128,7 +128,13 @@ func DomainHandler(c *gin.Context) {
return return
} }
domain, err := storage.MainStore.GetDomainByDN(user, c.Param("domain")) dnid, err := happydns.NewIdentifierFromString(c.Param("domain"))
if err != nil {
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": fmt.Sprintf("Invalid domain identifier: %s", err.Error())})
return
}
domain, err := storage.MainStore.GetDomain(user, dnid)
if err != nil { if err != nil {
c.AbortWithStatusJSON(http.StatusNotFound, gin.H{"errmsg": "Domain not found"}) c.AbortWithStatusJSON(http.StatusNotFound, gin.H{"errmsg": "Domain not found"})
return return
@ -141,7 +147,7 @@ func DomainHandler(c *gin.Context) {
} else if src, exists := c.Get("sourcemeta"); exists { } else if src, exists := c.Get("sourcemeta"); exists {
source = src.(*happydns.SourceMeta) source = src.(*happydns.SourceMeta)
} }
if source != nil && source.Id != domain.IdProvider { if source != nil && !source.Id.Equals(domain.IdProvider) {
c.AbortWithStatusJSON(http.StatusNotFound, gin.H{"errmsg": "Domain not found (not child of source)"}) c.AbortWithStatusJSON(http.StatusNotFound, gin.H{"errmsg": "Domain not found (not child of source)"})
return return
} }
@ -152,9 +158,9 @@ func DomainHandler(c *gin.Context) {
} }
type apiDomain struct { type apiDomain struct {
Id int64 `json:"id"` Id happydns.Identifier `json:"id"`
IdUser []byte `json:"id_owner"` IdUser happydns.Identifier `json:"id_owner"`
IdProvider int64 `json:"id_provider"` IdProvider happydns.Identifier `json:"id_provider"`
DomainName string `json:"domain"` DomainName string `json:"domain"`
ZoneHistory []happydns.ZoneMeta `json:"zone_history"` ZoneHistory []happydns.ZoneMeta `json:"zone_history"`
Group string `json:"group,omitempty"` Group string `json:"group,omitempty"`
@ -194,7 +200,7 @@ func UpdateDomain(c *gin.Context) {
return return
} }
if old.Id != domain.Id { if !old.Id.Equals(domain.Id) {
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": "You cannot change the domain reserved ID"}) c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": "You cannot change the domain reserved ID"})
return return
} }

View File

@ -111,7 +111,7 @@ func getProviderSettingsState(cfg *config.Options, c *gin.Context) {
return return
} else { } else {
// Update an existing Provider // Update an existing Provider
s, err := storage.MainStore.GetProvider(user, int64(uss.Id.(float64))) s, err := storage.MainStore.GetProvider(user, uss.Id.(happydns.Identifier))
if err != nil { if err != nil {
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": err.Error()}) c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": err.Error()})
return return

View File

@ -35,7 +35,6 @@ import (
"fmt" "fmt"
"log" "log"
"net/http" "net/http"
"strconv"
dnscontrol "github.com/StackExchange/dnscontrol/v3/providers" dnscontrol "github.com/StackExchange/dnscontrol/v3/providers"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
@ -110,7 +109,7 @@ func DecodeProvider(c *gin.Context) (*happydns.ProviderCombined, int, error) {
func ProviderMetaHandler(c *gin.Context) { func ProviderMetaHandler(c *gin.Context) {
// Extract provider ID // Extract provider ID
pid, err := strconv.ParseInt(string(c.Param("pid")), 10, 64) pid, err := happydns.NewIdentifierFromString(string(c.Param("pid")))
if err != nil { if err != nil {
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": fmt.Sprintf("Invalid provider id: %s", err.Error())}) c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": fmt.Sprintf("Invalid provider id: %s", err.Error())})
return return
@ -138,7 +137,7 @@ func ProviderMetaHandler(c *gin.Context) {
func ProviderHandler(c *gin.Context) { func ProviderHandler(c *gin.Context) {
// Extract provider ID // Extract provider ID
pid, err := strconv.ParseInt(string(c.Param("pid")), 10, 64) pid, err := happydns.NewIdentifierFromString(string(c.Param("pid")))
if err != nil { if err != nil {
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": fmt.Sprintf("Invalid provider id: %s", err.Error())}) c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": fmt.Sprintf("Invalid provider id: %s", err.Error())})
return return
@ -224,7 +223,7 @@ func deleteProvider(c *gin.Context) {
} }
for _, domain := range domains { for _, domain := range domains {
if domain.IdProvider == providermeta.Id { if domain.IdProvider.Equals(providermeta.Id) {
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": "You cannot delete this provider because there is still some domains associated with it."}) c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": "You cannot delete this provider because there is still some domains associated with it."})
return return
} }

View File

@ -71,7 +71,7 @@ func declareAuthenticationRoutes(opts *config.Options, router *gin.RouterGroup)
} }
type DisplayUser struct { type DisplayUser struct {
Id happydns.HexaString `json:"id"` Id happydns.Identifier `json:"id"`
Email string `json:"email"` Email string `json:"email"`
CreatedAt time.Time `json:"created_at,omitempty"` CreatedAt time.Time `json:"created_at,omitempty"`
Settings happydns.UserSettings `json:"settings,omitempty"` Settings happydns.UserSettings `json:"settings,omitempty"`

View File

@ -33,7 +33,7 @@ package api
import ( import (
"bytes" "bytes"
"encoding/hex" "encoding/base64"
"fmt" "fmt"
"log" "log"
"net/http" "net/http"
@ -356,7 +356,7 @@ func deleteUser(opts *config.Options, c *gin.Context) {
} }
func UserHandlerBase(c *gin.Context) (*happydns.User, error) { func UserHandlerBase(c *gin.Context) (*happydns.User, error) {
uid, err := hex.DecodeString(c.Param("uid")) uid, err := base64.RawURLEncoding.DecodeString(c.Param("uid"))
if err != nil { if err != nil {
return nil, fmt.Errorf("Invalid user identifier given: %w", err) return nil, fmt.Errorf("Invalid user identifier given: %w", err)
} }
@ -382,7 +382,7 @@ func userHandler(c *gin.Context) {
} }
func UserAuthHandlerBase(c *gin.Context) (*happydns.UserAuth, error) { func UserAuthHandlerBase(c *gin.Context) (*happydns.UserAuth, error) {
uid, err := hex.DecodeString(c.Param("uid")) uid, err := base64.RawURLEncoding.DecodeString(c.Param("uid"))
if err != nil { if err != nil {
return nil, fmt.Errorf("Invalid user identifier given: %w", err) return nil, fmt.Errorf("Invalid user identifier given: %w", err)
} }

View File

@ -32,11 +32,9 @@
package api package api
import ( import (
"encoding/hex"
"fmt" "fmt"
"log" "log"
"net/http" "net/http"
"strconv"
"strings" "strings"
"time" "time"
@ -78,7 +76,7 @@ func declareZonesRoutes(cfg *config.Options, router *gin.RouterGroup) {
} }
func loadZoneFromId(domain *happydns.Domain, id string) (*happydns.Zone, int, error) { func loadZoneFromId(domain *happydns.Domain, id string) (*happydns.Zone, int, error) {
zoneid, err := strconv.ParseInt(id, 10, 64) zoneid, err := happydns.NewIdentifierFromString(id)
if err != nil { if err != nil {
return nil, http.StatusBadRequest, fmt.Errorf("Invalid zoneid: %q", id) return nil, http.StatusBadRequest, fmt.Errorf("Invalid zoneid: %q", id)
} }
@ -168,7 +166,7 @@ func addZoneService(c *gin.Context) {
} }
func serviceIdHandler(c *gin.Context) { func serviceIdHandler(c *gin.Context) {
serviceid, err := hex.DecodeString(c.Param("serviceid")) serviceid, err := happydns.NewIdentifierFromString(c.Param("serviceid"))
if err != nil { if err != nil {
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": fmt.Sprintf("Bad service identifier: %s", err.Error())}) c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": fmt.Sprintf("Bad service identifier: %s", err.Error())})
return return
@ -226,7 +224,7 @@ func importZone(c *gin.Context) {
return return
} }
domain.ZoneHistory = append( domain.ZoneHistory = append(
[]int64{myZone.Id}, domain.ZoneHistory...) []happydns.Identifier{myZone.Id}, domain.ZoneHistory...)
// Create wip zone // Create wip zone
err = storage.MainStore.CreateZone(myZone) err = storage.MainStore.CreateZone(myZone)
@ -236,7 +234,7 @@ func importZone(c *gin.Context) {
return return
} }
domain.ZoneHistory = append( domain.ZoneHistory = append(
[]int64{myZone.Id}, domain.ZoneHistory...) []happydns.Identifier{myZone.Id}, domain.ZoneHistory...)
err = storage.MainStore.UpdateDomain(domain) err = storage.MainStore.UpdateDomain(domain)
if err != nil { if err != nil {
@ -359,7 +357,7 @@ func applyZone(c *gin.Context) {
} }
domain.ZoneHistory = append( domain.ZoneHistory = append(
[]int64{newZone.Id}, domain.ZoneHistory...) []happydns.Identifier{newZone.Id}, domain.ZoneHistory...)
err = storage.MainStore.UpdateDomain(domain) err = storage.MainStore.UpdateDomain(domain)
if err != nil { if err != nil {
@ -431,7 +429,7 @@ func UpdateZoneService(c *gin.Context) {
func deleteZoneService(c *gin.Context) { func deleteZoneService(c *gin.Context) {
domain := c.MustGet("domain").(*happydns.Domain) domain := c.MustGet("domain").(*happydns.Domain)
zone := c.MustGet("zone").(*happydns.Zone) zone := c.MustGet("zone").(*happydns.Zone)
serviceid := c.MustGet("serviceid").([]byte) serviceid := c.MustGet("serviceid").(happydns.Identifier)
subdomain := c.MustGet("subdomain").(string) subdomain := c.MustGet("subdomain").(string)
err := zone.EraseService(subdomain, domain.DomainName, serviceid, nil) err := zone.EraseService(subdomain, domain.DomainName, serviceid, nil)
@ -460,7 +458,7 @@ type serviceRecord struct {
func getServiceRecords(c *gin.Context) { func getServiceRecords(c *gin.Context) {
domain := c.MustGet("domain").(*happydns.Domain) domain := c.MustGet("domain").(*happydns.Domain)
zone := c.MustGet("zone").(*happydns.Zone) zone := c.MustGet("zone").(*happydns.Zone)
serviceid := c.MustGet("serviceid").([]byte) serviceid := c.MustGet("serviceid").(happydns.Identifier)
subdomain := c.MustGet("subdomain").(string) subdomain := c.MustGet("subdomain").(string)
svc := zone.FindSubdomainService(subdomain, serviceid) svc := zone.FindSubdomainService(subdomain, serviceid)

View File

@ -32,6 +32,7 @@
package config package config
import ( import (
"encoding/base64"
"net/url" "net/url"
"git.happydns.org/happydomain/model" "git.happydns.org/happydomain/model"
@ -40,11 +41,11 @@ import (
// GetAccountRecoveryURL returns the absolute URL corresponding to the recovery // GetAccountRecoveryURL returns the absolute URL corresponding to the recovery
// URL of the given account. // URL of the given account.
func (o *Options) GetAccountRecoveryURL(u *happydns.UserAuth) string { func (o *Options) GetAccountRecoveryURL(u *happydns.UserAuth) string {
return o.BuildURL_noescape("/forgotten-password?u=%x&k=%s", u.Id, url.QueryEscape(u.GenAccountRecoveryHash(false))) return o.BuildURL_noescape("/forgotten-password?u=%s&k=%s", base64.RawURLEncoding.EncodeToString(u.Id), url.QueryEscape(u.GenAccountRecoveryHash(false)))
} }
// GetRegistrationURL returns the absolute URL corresponding to the e-mail // GetRegistrationURL returns the absolute URL corresponding to the e-mail
// validation page of the given account. // validation page of the given account.
func (o *Options) GetRegistrationURL(u *happydns.UserAuth) string { func (o *Options) GetRegistrationURL(u *happydns.UserAuth) string {
return o.BuildURL_noescape("/email-validation?u=%x&k=%s", u.Id, url.QueryEscape(u.GenRegistrationHash(false))) return o.BuildURL_noescape("/email-validation?u=%s&k=%s", base64.RawURLEncoding.EncodeToString(u.Id), url.QueryEscape(u.GenRegistrationHash(false)))
} }

View File

@ -38,14 +38,14 @@ import (
// Domain holds information about a domain name own by a User. // Domain holds information about a domain name own by a User.
type Domain struct { type Domain struct {
// Id is the Domain's identifier in the database. // Id is the Domain's identifier in the database.
Id int64 `json:"id"` Id Identifier `json:"id"`
// IdUser is the identifier of the Domain's Owner. // IdUser is the identifier of the Domain's Owner.
IdUser HexaString `json:"id_owner"` IdUser Identifier `json:"id_owner"`
// IsProvider is the identifier of the Provider used to access and edit the // IsProvider is the identifier of the Provider used to access and edit the
// Domain. // Domain.
IdProvider int64 `json:"id_provider"` IdProvider Identifier `json:"id_provider"`
// DomainName is the FQDN of the managed Domain. // DomainName is the FQDN of the managed Domain.
DomainName string `json:"domain"` DomainName string `json:"domain"`
@ -55,7 +55,7 @@ type Domain struct {
// ZoneHistory are the identifiers to the Zone attached to the current // ZoneHistory are the identifiers to the Zone attached to the current
// Domain. // Domain.
ZoneHistory []int64 `json:"zone_history"` ZoneHistory []Identifier `json:"zone_history"`
} }
// Domains is an array of Domain. // Domains is an array of Domain.
@ -63,9 +63,9 @@ type Domains []*Domain
// HasZone checks if the given Zone's identifier is part of this Domain // HasZone checks if the given Zone's identifier is part of this Domain
// history. // history.
func (d *Domain) HasZone(zoneId int64) (found bool) { func (d *Domain) HasZone(zoneId Identifier) (found bool) {
for _, v := range d.ZoneHistory { for _, v := range d.ZoneHistory {
if v == zoneId { if v.Equals(zoneId) {
return true return true
} }
} }

88
model/identifier.go Normal file
View File

@ -0,0 +1,88 @@
// Copyright or © or Copr. happyDNS (2022)
//
// contact@happydomain.org
//
// This software is a computer program whose purpose is to provide a modern
// interface to interact with DNS systems.
//
// This software is governed by the CeCILL license under French law and abiding
// by the rules of distribution of free software. You can use, modify and/or
// redistribute the software under the terms of the CeCILL license as
// circulated by CEA, CNRS and INRIA at the following URL
// "http://www.cecill.info".
//
// As a counterpart to the access to the source code and rights to copy, modify
// and redistribute granted by the license, users are provided only with a
// limited warranty and the software's author, the holder of the economic
// rights, and the successive licensors have only limited liability.
//
// In this respect, the user's attention is drawn to the risks associated with
// loading, using, modifying and/or developing or reproducing the software by
// the user in light of its specific status of free software, that may mean
// that it is complicated to manipulate, and that also therefore means that it
// is reserved for developers and experienced professionals having in-depth
// computer knowledge. Users are therefore encouraged to load and test the
// software's suitability as regards their requirements in conditions enabling
// the security of their systems and/or data to be ensured and, more generally,
// to use and operate it in the same conditions as regards security.
//
// The fact that you are presently reading this means that you have had
// knowledge of the CeCILL license and that you accept its terms.
package happydns
import (
"bytes"
"crypto/rand"
"encoding/base64"
"errors"
)
const IDENTIFIER_LEN = 16
type Identifier []byte
func NewIdentifierFromString(src string) (id Identifier, err error) {
return base64.RawURLEncoding.DecodeString(src)
}
func NewRandomIdentifier() (id Identifier, err error) {
id = make([]byte, IDENTIFIER_LEN)
if _, err = rand.Read(id); err != nil {
return
}
return
}
func (i *Identifier) IsEmpty() bool {
return len(*i) == 0
}
func (i Identifier) Equals(other Identifier) bool {
return bytes.Equal(i, other)
}
func (i *Identifier) String() string {
return base64.RawURLEncoding.EncodeToString(*i)
}
func (i Identifier) MarshalJSON() (dst []byte, err error) {
dst = make([]byte, base64.RawURLEncoding.EncodedLen(len(i)))
base64.RawURLEncoding.Encode(dst, i)
dst = append([]byte{'"'}, dst...)
dst = append(dst, '"')
return
}
func (i *Identifier) UnmarshalJSON(src []byte) error {
if len(src) < 2 || src[0] != '"' || src[len(src)-1] != '"' {
return errors.New("Unvalid character found to encapsulate the JSON value")
}
*i = make([]byte, base64.RawURLEncoding.DecodedLen(len(src)-2))
_, err := base64.RawURLEncoding.Decode(*i, src[1:len(src)-1])
return err
}

View File

@ -52,10 +52,10 @@ type ProviderMeta struct {
Type string `json:"_srctype"` Type string `json:"_srctype"`
// Id is the Provider's identifier. // Id is the Provider's identifier.
Id int64 `json:"_id"` Id Identifier `json:"_id"`
// OwnerId is the User's identifier for the current Provider. // OwnerId is the User's identifier for the current Provider.
OwnerId HexaString `json:"_ownerid"` OwnerId Identifier `json:"_ownerid"`
// Comment is a string that helps user to distinguish the Provider. // Comment is a string that helps user to distinguish the Provider.
Comment string `json:"_comment,omitempty"` Comment string `json:"_comment,omitempty"`

View File

@ -57,10 +57,10 @@ type ServiceMeta struct {
Type string `json:"_svctype"` Type string `json:"_svctype"`
// Id is the Service's identifier. // Id is the Service's identifier.
Id HexaString `json:"_id,omitempty"` Id Identifier `json:"_id,omitempty"`
// OwnerId is the User's identifier for the current Service. // OwnerId is the User's identifier for the current Service.
OwnerId HexaString `json:"_ownerid,omitempty"` OwnerId Identifier `json:"_ownerid,omitempty"`
// Domain contains the abstract domain where this Service relates. // Domain contains the abstract domain where this Service relates.
Domain string `json:"_domain"` Domain string `json:"_domain"`

View File

@ -42,10 +42,10 @@ import (
// Session holds informatin about a User's currently connected. // Session holds informatin about a User's currently connected.
type Session struct { type Session struct {
// Id is the Session's identifier. // Id is the Session's identifier.
Id []byte `json:"id"` Id Identifier `json:"id"`
// IdUser is the User's identifier of the Session. // IdUser is the User's identifier of the Session.
IdUser HexaString `json:"login"` IdUser Identifier `json:"login"`
// IssuedAt holds the creation date of the Session. // IssuedAt holds the creation date of the Session.
IssuedAt time.Time `json:"time"` IssuedAt time.Time `json:"time"`

View File

@ -63,10 +63,10 @@ type SourceMeta struct {
Type string `json:"_srctype"` Type string `json:"_srctype"`
// Id is the Source's identifier. // Id is the Source's identifier.
Id int64 `json:"_id"` Id Identifier `json:"_id"`
// OwnerId is the User's identifier for the current Source. // OwnerId is the User's identifier for the current Source.
OwnerId []byte `json:"_ownerid"` OwnerId Identifier `json:"_ownerid"`
// Comment is a string that helps user to distinguish the Source. // Comment is a string that helps user to distinguish the Source.
Comment string `json:"_comment,omitempty"` Comment string `json:"_comment,omitempty"`

View File

@ -38,7 +38,7 @@ import (
// User represents an account. // User represents an account.
type User struct { type User struct {
// Id is the User's identifier. // Id is the User's identifier.
Id HexaString Id Identifier
// Email is the User's login and mean of contact. // Email is the User's login and mean of contact.
Email string Email string

View File

@ -46,7 +46,7 @@ import (
// UserAuth represents an account used for authentication (not used in case of external auth). // UserAuth represents an account used for authentication (not used in case of external auth).
type UserAuth struct { type UserAuth struct {
// Id is the User's identifier. // Id is the User's identifier.
Id []byte Id Identifier
// Email is the User's login and mean of contact. // Email is the User's login and mean of contact.
Email string Email string

View File

@ -42,10 +42,10 @@ import (
// ZoneMeta holds the metadata associated to a Zone. // ZoneMeta holds the metadata associated to a Zone.
type ZoneMeta struct { type ZoneMeta struct {
// Id is the Zone's identifier. // Id is the Zone's identifier.
Id int64 `json:"id"` Id Identifier `json:"id"`
// IdAuthor is the User's identifier for the current Zone. // IdAuthor is the User's identifier for the current Zone.
IdAuthor HexaString `json:"id_author"` IdAuthor Identifier `json:"id_author"`
// DefaultTTL is the TTL to use when no TTL has been defined for a record in this Zone. // DefaultTTL is the TTL to use when no TTL has been defined for a record in this Zone.
DefaultTTL uint32 `json:"default_ttl"` DefaultTTL uint32 `json:"default_ttl"`

File diff suppressed because one or more lines are too long

View File

@ -51,7 +51,7 @@ type Storage interface {
GetAuthUsers() (happydns.UserAuths, error) GetAuthUsers() (happydns.UserAuths, error)
// GetAuthUser retrieves the User with the given identifier. // GetAuthUser retrieves the User with the given identifier.
GetAuthUser(id []byte) (*happydns.UserAuth, error) GetAuthUser(id happydns.Identifier) (*happydns.UserAuth, error)
// GetAuthUserByEmail retrives the User with the given email address. // GetAuthUserByEmail retrives the User with the given email address.
GetAuthUserByEmail(email string) (*happydns.UserAuth, error) GetAuthUserByEmail(email string) (*happydns.UserAuth, error)
@ -77,7 +77,7 @@ type Storage interface {
GetDomains(u *happydns.User) (happydns.Domains, error) GetDomains(u *happydns.User) (happydns.Domains, error)
// GetDomain retrieves the Domain with the given id and owned by the given User. // GetDomain retrieves the Domain with the given id and owned by the given User.
GetDomain(u *happydns.User, id int64) (*happydns.Domain, error) GetDomain(u *happydns.User, id happydns.Identifier) (*happydns.Domain, error)
// GetDomainByDN is like GetDomain but look for the domain name instead of identifier. // GetDomainByDN is like GetDomain but look for the domain name instead of identifier.
GetDomainByDN(u *happydns.User, dn string) (*happydns.Domain, error) GetDomainByDN(u *happydns.User, dn string) (*happydns.Domain, error)
@ -106,10 +106,10 @@ type Storage interface {
GetProviderMetas(u *happydns.User) ([]happydns.ProviderMeta, error) GetProviderMetas(u *happydns.User) ([]happydns.ProviderMeta, error)
// GetProviderMeta retrieves the metadatas for the Provider with the given identifier and owner. // GetProviderMeta retrieves the metadatas for the Provider with the given identifier and owner.
GetProviderMeta(u *happydns.User, id int64) (*happydns.ProviderMeta, error) GetProviderMeta(u *happydns.User, id happydns.Identifier) (*happydns.ProviderMeta, error)
// GetProvider retrieves the full Provider with the given identifier and owner. // GetProvider retrieves the full Provider with the given identifier and owner.
GetProvider(u *happydns.User, id int64) (*happydns.ProviderCombined, error) GetProvider(u *happydns.User, id happydns.Identifier) (*happydns.ProviderCombined, error)
// CreateProvider creates a record in the database for the given Provider. // CreateProvider creates a record in the database for the given Provider.
CreateProvider(u *happydns.User, s happydns.Provider, comment string) (*happydns.ProviderCombined, error) CreateProvider(u *happydns.User, s happydns.Provider, comment string) (*happydns.ProviderCombined, error)
@ -129,7 +129,7 @@ type Storage interface {
// SESSIONS --------------------------------------------------- // SESSIONS ---------------------------------------------------
// GetSession retrieves the Session with the given identifier. // GetSession retrieves the Session with the given identifier.
GetSession(id []byte) (*happydns.Session, error) GetSession(id happydns.Identifier) (*happydns.Session, error)
// GetAuthUserSessions retrieves all Session for the given AuthUser. // GetAuthUserSessions retrieves all Session for the given AuthUser.
GetAuthUserSessions(user *happydns.UserAuth) ([]*happydns.Session, error) GetAuthUserSessions(user *happydns.UserAuth) ([]*happydns.Session, error)
@ -155,7 +155,7 @@ type Storage interface {
GetUsers() (happydns.Users, error) GetUsers() (happydns.Users, error)
// GetUser retrieves the User with the given identifier. // GetUser retrieves the User with the given identifier.
GetUser(id []byte) (*happydns.User, error) GetUser(id happydns.Identifier) (*happydns.User, error)
// GetUserByEmail retrives the User with the given email address. // GetUserByEmail retrives the User with the given email address.
GetUserByEmail(email string) (*happydns.User, error) GetUserByEmail(email string) (*happydns.User, error)
@ -175,10 +175,10 @@ type Storage interface {
// ZONES ------------------------------------------------------ // ZONES ------------------------------------------------------
// GetZoneMeta retrives metadatas of the Zone with the given identifier. // GetZoneMeta retrives metadatas of the Zone with the given identifier.
GetZoneMeta(id int64) (*happydns.ZoneMeta, error) GetZoneMeta(id happydns.Identifier) (*happydns.ZoneMeta, error)
// GetZone retrieves the full Zone (including Services and metadatas) which have the given identifier. // GetZone retrieves the full Zone (including Services and metadatas) which have the given identifier.
GetZone(id int64) (*happydns.Zone, error) GetZone(id happydns.Identifier) (*happydns.Zone, error)
// CreateZone creates a record in the database for the given Zone. // CreateZone creates a record in the database for the given Zone.
CreateZone(zone *happydns.Zone) error CreateZone(zone *happydns.Zone) error

View File

@ -62,9 +62,9 @@ func (s *LevelDBStorage) GetAuthUsers() (users happydns.UserAuths, err error) {
return return
} }
func (s *LevelDBStorage) GetAuthUser(id []byte) (u *happydns.UserAuth, err error) { func (s *LevelDBStorage) GetAuthUser(id happydns.Identifier) (u *happydns.UserAuth, err error) {
u = &happydns.UserAuth{} u = &happydns.UserAuth{}
err = s.get(fmt.Sprintf("auth-%x", id), &u) err = s.get(fmt.Sprintf("auth-%s", id.String()), &u)
return return
} }
@ -102,7 +102,7 @@ func (s *LevelDBStorage) AuthUserExists(email string) bool {
} }
func (s *LevelDBStorage) CreateAuthUser(u *happydns.UserAuth) error { func (s *LevelDBStorage) CreateAuthUser(u *happydns.UserAuth) error {
key, id, err := s.findBytesKey("auth-", 16) key, id, err := s.findIdentifierKey("auth-")
if err != nil { if err != nil {
return err return err
} }
@ -112,11 +112,11 @@ func (s *LevelDBStorage) CreateAuthUser(u *happydns.UserAuth) error {
} }
func (s *LevelDBStorage) UpdateAuthUser(u *happydns.UserAuth) error { func (s *LevelDBStorage) UpdateAuthUser(u *happydns.UserAuth) error {
return s.put(fmt.Sprintf("auth-%x", u.Id), u) return s.put(fmt.Sprintf("auth-%s", u.Id.String()), u)
} }
func (s *LevelDBStorage) DeleteAuthUser(u *happydns.UserAuth) error { func (s *LevelDBStorage) DeleteAuthUser(u *happydns.UserAuth) error {
return s.delete(fmt.Sprintf("auth-%x", u.Id)) return s.delete(fmt.Sprintf("auth-%s", u.Id.String()))
} }
func (s *LevelDBStorage) ClearAuthUsers() error { func (s *LevelDBStorage) ClearAuthUsers() error {

View File

@ -32,11 +32,11 @@
package database // import "happydns.org/storage/leveldb" package database // import "happydns.org/storage/leveldb"
import ( import (
crand "crypto/rand"
"encoding/json" "encoding/json"
"fmt" "fmt"
"log" "log"
mrand "math/rand"
"git.happydns.org/happydomain/model"
"github.com/syndtr/goleveldb/leveldb" "github.com/syndtr/goleveldb/leveldb"
"github.com/syndtr/goleveldb/leveldb/errors" "github.com/syndtr/goleveldb/leveldb/errors"
@ -105,29 +105,14 @@ func (s *LevelDBStorage) put(key string, v interface{}) error {
return s.db.Put([]byte(key), data, nil) return s.db.Put([]byte(key), data, nil)
} }
func (s *LevelDBStorage) findInt63Key(prefix string) (key string, id int64, err error) { func (s *LevelDBStorage) findIdentifierKey(prefix string) (key string, id happydns.Identifier, err error) {
found := true found := true
for found { for found {
// max random id is 2^53 to fit on float64 without loosing precision (JSON limitation) id, err = happydns.NewRandomIdentifier()
id = mrand.Int63n(1 << 53)
key = fmt.Sprintf("%s%d", prefix, id)
found, err = s.db.Has([]byte(key), nil)
if err != nil { if err != nil {
return return
} }
} key = fmt.Sprintf("%s%s", prefix, id.String())
return
}
func (s *LevelDBStorage) findBytesKey(prefix string, len int) (key string, id []byte, err error) {
id = make([]byte, len)
found := true
for found {
if _, err = crand.Read(id); err != nil {
return
}
key = fmt.Sprintf("%s%x", prefix, id)
found, err = s.db.Has([]byte(key), nil) found, err = s.db.Has([]byte(key), nil)
if err != nil { if err != nil {

View File

@ -68,8 +68,8 @@ func (s *LevelDBStorage) getDomain(id string) (z *happydns.Domain, err error) {
return return
} }
func (s *LevelDBStorage) GetDomain(u *happydns.User, id int64) (z *happydns.Domain, err error) { func (s *LevelDBStorage) GetDomain(u *happydns.User, id happydns.Identifier) (z *happydns.Domain, err error) {
z, err = s.getDomain(fmt.Sprintf("domain-%d", id)) z, err = s.getDomain(fmt.Sprintf("domain-%s", id.String()))
if err != nil { if err != nil {
return return
@ -119,7 +119,7 @@ func (s *LevelDBStorage) DomainExists(dn string) bool {
} }
func (s *LevelDBStorage) CreateDomain(u *happydns.User, z *happydns.Domain) error { func (s *LevelDBStorage) CreateDomain(u *happydns.User, z *happydns.Domain) error {
key, id, err := s.findInt63Key("domain-") key, id, err := s.findIdentifierKey("domain-")
if err != nil { if err != nil {
return err return err
} }
@ -130,16 +130,16 @@ func (s *LevelDBStorage) CreateDomain(u *happydns.User, z *happydns.Domain) erro
} }
func (s *LevelDBStorage) UpdateDomain(z *happydns.Domain) error { func (s *LevelDBStorage) UpdateDomain(z *happydns.Domain) error {
return s.put(fmt.Sprintf("domain-%d", z.Id), z) return s.put(fmt.Sprintf("domain-%s", z.Id.String()), z)
} }
func (s *LevelDBStorage) UpdateDomainOwner(z *happydns.Domain, newOwner *happydns.User) error { func (s *LevelDBStorage) UpdateDomainOwner(z *happydns.Domain, newOwner *happydns.User) error {
z.IdUser = newOwner.Id z.IdUser = newOwner.Id
return s.put(fmt.Sprintf("domain-%d", z.Id), z) return s.put(fmt.Sprintf("domain-%s", z.Id.String()), z)
} }
func (s *LevelDBStorage) DeleteDomain(z *happydns.Domain) error { func (s *LevelDBStorage) DeleteDomain(z *happydns.Domain) error {
return s.delete(fmt.Sprintf("domain-%d", z.Id)) return s.delete(fmt.Sprintf("domain-%s", z.Id.String()))
} }
func (s *LevelDBStorage) ClearDomains() error { func (s *LevelDBStorage) ClearDomains() error {
@ -191,18 +191,18 @@ func (s *LevelDBStorage) TidyDomains() error {
if err == leveldb.ErrNotFound { if err == leveldb.ErrNotFound {
// Drop domain of unexistant users // Drop domain of unexistant users
err = tx.Delete(iter.Key(), nil) err = tx.Delete(iter.Key(), nil)
log.Printf("Deleting orphan domain (user %d not found): %v\n", domain.IdUser, domain) log.Printf("Deleting orphan domain (user %s not found): %v\n", domain.IdUser.String(), domain)
} }
_, err = s.GetProvider(u, domain.IdProvider) _, err = s.GetProvider(u, domain.IdProvider)
if err == leveldb.ErrNotFound { if err == leveldb.ErrNotFound {
// Drop domain of unexistant provider // Drop domain of unexistant provider
err = tx.Delete(iter.Key(), nil) err = tx.Delete(iter.Key(), nil)
log.Printf("Deleting orphan domain (provider %d not found): %v\n", domain.IdProvider, domain) log.Printf("Deleting orphan domain (provider %s not found): %v\n", domain.IdProvider.String(), domain)
} }
} else { } else {
// Drop unreadable domains // Drop unreadable domains
log.Printf("Deleting unreadable domain (%w): %v\n", err, domain) log.Printf("Deleting unreadable domain (%s): %v\n", err.Error(), domain)
err = tx.Delete(iter.Key(), nil) err = tx.Delete(iter.Key(), nil)
} }

View File

@ -44,7 +44,7 @@ import (
"git.happydns.org/happydomain/providers" "git.happydns.org/happydomain/providers"
) )
func (s *LevelDBStorage) getProviderMeta(id []byte) (srcMeta *happydns.ProviderMeta, err error) { func (s *LevelDBStorage) getProviderMeta(id happydns.Identifier) (srcMeta *happydns.ProviderMeta, err error) {
var v []byte var v []byte
v, err = s.db.Get(id, nil) v, err = s.db.Get(id, nil)
if err != nil { if err != nil {
@ -77,9 +77,9 @@ func (s *LevelDBStorage) GetProviderMetas(u *happydns.User) (srcs []happydns.Pro
return return
} }
func (s *LevelDBStorage) GetProviderMeta(u *happydns.User, id int64) (srcMeta *happydns.ProviderMeta, err error) { func (s *LevelDBStorage) GetProviderMeta(u *happydns.User, id happydns.Identifier) (srcMeta *happydns.ProviderMeta, err error) {
var v []byte var v []byte
v, err = s.db.Get([]byte(fmt.Sprintf("provider-%d", id)), nil) v, err = s.db.Get([]byte(fmt.Sprintf("provider-%s", id.String())), nil)
if err != nil { if err != nil {
return return
} }
@ -98,9 +98,9 @@ func (s *LevelDBStorage) GetProviderMeta(u *happydns.User, id int64) (srcMeta *h
return return
} }
func (s *LevelDBStorage) GetProvider(u *happydns.User, id int64) (src *happydns.ProviderCombined, err error) { func (s *LevelDBStorage) GetProvider(u *happydns.User, id happydns.Identifier) (src *happydns.ProviderCombined, err error) {
var v []byte var v []byte
v, err = s.db.Get([]byte(fmt.Sprintf("provider-%d", id)), nil) v, err = s.db.Get([]byte(fmt.Sprintf("provider-%s", id.String())), nil)
if err != nil { if err != nil {
return return
} }
@ -130,7 +130,7 @@ func (s *LevelDBStorage) GetProvider(u *happydns.User, id int64) (src *happydns.
} }
func (s *LevelDBStorage) CreateProvider(u *happydns.User, src happydns.Provider, comment string) (*happydns.ProviderCombined, error) { func (s *LevelDBStorage) CreateProvider(u *happydns.User, src happydns.Provider, comment string) (*happydns.ProviderCombined, error) {
key, id, err := s.findInt63Key("provider-") key, id, err := s.findIdentifierKey("provider-")
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -150,7 +150,7 @@ func (s *LevelDBStorage) CreateProvider(u *happydns.User, src happydns.Provider,
} }
func (s *LevelDBStorage) UpdateProvider(src *happydns.ProviderCombined) error { func (s *LevelDBStorage) UpdateProvider(src *happydns.ProviderCombined) error {
return s.put(fmt.Sprintf("provider-%d", src.Id), src) return s.put(fmt.Sprintf("provider-%s", src.Id.String()), src)
} }
func (s *LevelDBStorage) UpdateProviderOwner(src *happydns.ProviderCombined, newOwner *happydns.User) error { func (s *LevelDBStorage) UpdateProviderOwner(src *happydns.ProviderCombined, newOwner *happydns.User) error {
@ -159,7 +159,7 @@ func (s *LevelDBStorage) UpdateProviderOwner(src *happydns.ProviderCombined, new
} }
func (s *LevelDBStorage) DeleteProvider(src *happydns.ProviderMeta) error { func (s *LevelDBStorage) DeleteProvider(src *happydns.ProviderMeta) error {
return s.delete(fmt.Sprintf("provider-%d", src.Id)) return s.delete(fmt.Sprintf("provider-%s", src.Id.String()))
} }
func (s *LevelDBStorage) ClearProviders() error { func (s *LevelDBStorage) ClearProviders() error {
@ -202,13 +202,13 @@ func (s *LevelDBStorage) TidyProviders() error {
if err != nil { if err != nil {
// Drop unreadable providers // Drop unreadable providers
log.Printf("Deleting unreadable provider (%w): %v\n", err, srcMeta) log.Printf("Deleting unreadable provider (%s): %v\n", err.Error(), srcMeta)
err = tx.Delete(iter.Key(), nil) err = tx.Delete(iter.Key(), nil)
} else { } else {
_, err = s.GetUser(srcMeta.OwnerId) _, err = s.GetUser(srcMeta.OwnerId)
if err == leveldb.ErrNotFound { if err == leveldb.ErrNotFound {
// Drop providers of unexistant users // Drop providers of unexistant users
log.Printf("Deleting orphan provider (user %d not found): %v\n", srcMeta.OwnerId, srcMeta) log.Printf("Deleting orphan provider (user %s not found): %v\n", srcMeta.OwnerId.String(), srcMeta)
err = tx.Delete(iter.Key(), nil) err = tx.Delete(iter.Key(), nil)
} }
} }

View File

@ -47,8 +47,8 @@ func (s *LevelDBStorage) getSession(id string) (session *happydns.Session, err e
return return
} }
func (s *LevelDBStorage) GetSession(id []byte) (session *happydns.Session, err error) { func (s *LevelDBStorage) GetSession(id happydns.Identifier) (session *happydns.Session, err error) {
return s.getSession(fmt.Sprintf("user.session-%x", id)) return s.getSession(fmt.Sprintf("user.session-%s", id.String()))
} }
func (s *LevelDBStorage) GetAuthUserSessions(user *happydns.UserAuth) (sessions []*happydns.Session, err error) { func (s *LevelDBStorage) GetAuthUserSessions(user *happydns.UserAuth) (sessions []*happydns.Session, err error) {
@ -86,7 +86,7 @@ func (s *LevelDBStorage) GetUserSessions(user *happydns.User) (sessions []*happy
} }
func (s *LevelDBStorage) CreateSession(session *happydns.Session) error { func (s *LevelDBStorage) CreateSession(session *happydns.Session) error {
key, id, err := s.findBytesKey("user.session-", 16) key, id, err := s.findIdentifierKey("user.session-")
if err != nil { if err != nil {
return err return err
} }
@ -97,11 +97,11 @@ func (s *LevelDBStorage) CreateSession(session *happydns.Session) error {
} }
func (s *LevelDBStorage) UpdateSession(session *happydns.Session) error { func (s *LevelDBStorage) UpdateSession(session *happydns.Session) error {
return s.put(fmt.Sprintf("user.session-%x", session.Id), session) return s.put(fmt.Sprintf("user.session-%s", session.Id.String()), session)
} }
func (s *LevelDBStorage) DeleteSession(session *happydns.Session) error { func (s *LevelDBStorage) DeleteSession(session *happydns.Session) error {
return s.delete(fmt.Sprintf("user.session-%x", session.Id)) return s.delete(fmt.Sprintf("user.session-%s", session.Id.String()))
} }
func (s *LevelDBStorage) ClearSessions() error { func (s *LevelDBStorage) ClearSessions() error {
@ -144,13 +144,13 @@ func (s *LevelDBStorage) TidySessions() error {
if err != nil { if err != nil {
// Drop unreadable sessions // Drop unreadable sessions
log.Printf("Deleting unreadable session (%w): %v\n", err, session) log.Printf("Deleting unreadable session (%s): %v\n", err.Error(), session)
err = tx.Delete(iter.Key(), nil) err = tx.Delete(iter.Key(), nil)
} else { } else {
_, err = s.GetUser(session.IdUser) _, err = s.GetUser(session.IdUser)
if err == leveldb.ErrNotFound { if err == leveldb.ErrNotFound {
// Drop session from unexistant users // Drop session from unexistant users
log.Printf("Deleting orphan session (user %d not found): %v\n", session.IdUser, session) log.Printf("Deleting orphan session (user %s not found): %v\n", session.IdUser.String(), session)
err = tx.Delete(iter.Key(), nil) err = tx.Delete(iter.Key(), nil)
} }
} }

View File

@ -62,9 +62,9 @@ func (s *LevelDBStorage) GetUsers() (users happydns.Users, err error) {
return return
} }
func (s *LevelDBStorage) GetUser(id []byte) (u *happydns.User, err error) { func (s *LevelDBStorage) GetUser(id happydns.Identifier) (u *happydns.User, err error) {
u = &happydns.User{} u = &happydns.User{}
err = s.get(fmt.Sprintf("user-%x", id), &u) err = s.get(fmt.Sprintf("user-%s", id.String()), &u)
return return
} }
@ -102,7 +102,7 @@ func (s *LevelDBStorage) UserExists(email string) bool {
} }
func (s *LevelDBStorage) CreateUser(u *happydns.User) error { func (s *LevelDBStorage) CreateUser(u *happydns.User) error {
key, id, err := s.findBytesKey("user-", 16) key, id, err := s.findIdentifierKey("user-")
if err != nil { if err != nil {
return err return err
} }
@ -112,11 +112,11 @@ func (s *LevelDBStorage) CreateUser(u *happydns.User) error {
} }
func (s *LevelDBStorage) UpdateUser(u *happydns.User) error { func (s *LevelDBStorage) UpdateUser(u *happydns.User) error {
return s.put(fmt.Sprintf("user-%x", u.Id), u) return s.put(fmt.Sprintf("user-%s", u.Id.String()), u)
} }
func (s *LevelDBStorage) DeleteUser(u *happydns.User) error { func (s *LevelDBStorage) DeleteUser(u *happydns.User) error {
return s.delete(fmt.Sprintf("user-%x", u.Id)) return s.delete(fmt.Sprintf("user-%s", u.Id.String()))
} }
func (s *LevelDBStorage) ClearUsers() error { func (s *LevelDBStorage) ClearUsers() error {

View File

@ -34,7 +34,6 @@ package database
import ( import (
"fmt" "fmt"
"log" "log"
"strconv"
"strings" "strings"
"git.happydns.org/happydomain/model" "git.happydns.org/happydomain/model"
@ -42,9 +41,9 @@ import (
"github.com/syndtr/goleveldb/leveldb/util" "github.com/syndtr/goleveldb/leveldb/util"
) )
func (s *LevelDBStorage) GetZone(id int64) (z *happydns.Zone, err error) { func (s *LevelDBStorage) GetZone(id happydns.Identifier) (z *happydns.Zone, err error) {
z = &happydns.Zone{} z = &happydns.Zone{}
err = s.get(fmt.Sprintf("domain.zone-%d", id), &z) err = s.get(fmt.Sprintf("domain.zone-%s", id.String()), &z)
return return
} }
@ -54,13 +53,13 @@ func (s *LevelDBStorage) getZoneMeta(id string) (z *happydns.ZoneMeta, err error
return return
} }
func (s *LevelDBStorage) GetZoneMeta(id int64) (z *happydns.ZoneMeta, err error) { func (s *LevelDBStorage) GetZoneMeta(id happydns.Identifier) (z *happydns.ZoneMeta, err error) {
z, err = s.getZoneMeta(fmt.Sprintf("domain.zone-%d", id)) z, err = s.getZoneMeta(fmt.Sprintf("domain.zone-%s", id.String()))
return return
} }
func (s *LevelDBStorage) CreateZone(z *happydns.Zone) error { func (s *LevelDBStorage) CreateZone(z *happydns.Zone) error {
key, id, err := s.findInt63Key("domain.zone-") key, id, err := s.findIdentifierKey("domain.zone-")
if err != nil { if err != nil {
return err return err
} }
@ -70,11 +69,11 @@ func (s *LevelDBStorage) CreateZone(z *happydns.Zone) error {
} }
func (s *LevelDBStorage) UpdateZone(z *happydns.Zone) error { func (s *LevelDBStorage) UpdateZone(z *happydns.Zone) error {
return s.put(fmt.Sprintf("domain.zone-%d", z.Id), z) return s.put(fmt.Sprintf("domain.zone-%s", z.Id.String()), z)
} }
func (s *LevelDBStorage) DeleteZone(z *happydns.Zone) error { func (s *LevelDBStorage) DeleteZone(z *happydns.Zone) error {
return s.delete(fmt.Sprintf("domain.zone-%d", z.Id)) return s.delete(fmt.Sprintf("domain.zone-%s", z.Id.String()))
} }
func (s *LevelDBStorage) ClearZones() error { func (s *LevelDBStorage) ClearZones() error {
@ -112,7 +111,7 @@ func (s *LevelDBStorage) TidyZones() error {
iter := tx.NewIterator(util.BytesPrefix([]byte("domain-")), nil) iter := tx.NewIterator(util.BytesPrefix([]byte("domain-")), nil)
defer iter.Release() defer iter.Release()
var referencedZones []int64 var referencedZones []happydns.Identifier
for iter.Next() { for iter.Next() {
domain, _ := s.getDomain(string(iter.Key())) domain, _ := s.getDomain(string(iter.Key()))
@ -128,14 +127,14 @@ func (s *LevelDBStorage) TidyZones() error {
defer iter.Release() defer iter.Release()
for iter.Next() { for iter.Next() {
if zoneId, err := strconv.ParseInt(strings.TrimPrefix(string(iter.Key()), "domain.zone-"), 10, 64); err != nil { if zoneId, err := happydns.NewIdentifierFromString(strings.TrimPrefix(string(iter.Key()), "domain.zone-")); err != nil {
// Drop zones with invalid ID // Drop zones with invalid ID
log.Printf("Deleting unindentified zone: key=%s\n", iter.Key()) log.Printf("Deleting unindentified zone: key=%s\n", iter.Key())
err = tx.Delete(iter.Key(), nil) err = tx.Delete(iter.Key(), nil)
} else { } else {
foundZone := false foundZone := false
for _, zid := range referencedZones { for _, zid := range referencedZones {
if zid == zoneId { if zid.Equals(zoneId) {
foundZone = true foundZone = true
break break
} }
@ -143,7 +142,7 @@ func (s *LevelDBStorage) TidyZones() error {
if !foundZone { if !foundZone {
// Drop orphan zones // Drop orphan zones
log.Printf("Deleting orphan zone: %d\n", zoneId) log.Printf("Deleting orphan zone: %s\n", zoneId.String())
err = tx.Delete(iter.Key(), nil) err = tx.Delete(iter.Key(), nil)
} }
} }