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"
"fmt"
"net/http"
"strconv"
"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())})
return
}
ud.Id = 0
ud.Id = nil
ud.IdUser = user.Id
ApiResponse(c, ud, storage.MainStore.CreateDomain(user, ud))
@ -126,7 +125,7 @@ func updateUserDomain(c *gin.Context) {
func deleteUserDomain(c *gin.Context) {
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 {
domain, err := storage.MainStore.GetDomainByDN(user, c.Param("domain"))
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())})
return
}
us.Id = 0
us.Id = nil
src, err := storage.MainStore.CreateProvider(user.(*happydns.User), us, "")
ApiResponse(c, src, err)

View File

@ -35,7 +35,6 @@ import (
"encoding/base64"
"fmt"
"net/http"
"strconv"
"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())})
return
}
uz.Id = 0
uz.Id = nil
ApiResponse(c, uz, storage.MainStore.CreateZone(uz))
}
@ -167,7 +166,7 @@ func patchZoneService(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 {
c.AbortWithStatusJSON(http.StatusNotFound, gin.H{"errmsg": err.Error()})
} else {

View File

@ -128,7 +128,13 @@ func DomainHandler(c *gin.Context) {
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 {
c.AbortWithStatusJSON(http.StatusNotFound, gin.H{"errmsg": "Domain not found"})
return
@ -141,7 +147,7 @@ func DomainHandler(c *gin.Context) {
} else if src, exists := c.Get("sourcemeta"); exists {
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)"})
return
}
@ -152,9 +158,9 @@ func DomainHandler(c *gin.Context) {
}
type apiDomain struct {
Id int64 `json:"id"`
IdUser []byte `json:"id_owner"`
IdProvider int64 `json:"id_provider"`
Id happydns.Identifier `json:"id"`
IdUser happydns.Identifier `json:"id_owner"`
IdProvider happydns.Identifier `json:"id_provider"`
DomainName string `json:"domain"`
ZoneHistory []happydns.ZoneMeta `json:"zone_history"`
Group string `json:"group,omitempty"`
@ -194,7 +200,7 @@ func UpdateDomain(c *gin.Context) {
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"})
return
}

View File

@ -111,7 +111,7 @@ func getProviderSettingsState(cfg *config.Options, c *gin.Context) {
return
} else {
// 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 {
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": err.Error()})
return

View File

@ -35,7 +35,6 @@ import (
"fmt"
"log"
"net/http"
"strconv"
dnscontrol "github.com/StackExchange/dnscontrol/v3/providers"
"github.com/gin-gonic/gin"
@ -110,7 +109,7 @@ func DecodeProvider(c *gin.Context) (*happydns.ProviderCombined, int, error) {
func ProviderMetaHandler(c *gin.Context) {
// Extract provider ID
pid, err := strconv.ParseInt(string(c.Param("pid")), 10, 64)
pid, err := happydns.NewIdentifierFromString(string(c.Param("pid")))
if err != nil {
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": fmt.Sprintf("Invalid provider id: %s", err.Error())})
return
@ -138,7 +137,7 @@ func ProviderMetaHandler(c *gin.Context) {
func ProviderHandler(c *gin.Context) {
// Extract provider ID
pid, err := strconv.ParseInt(string(c.Param("pid")), 10, 64)
pid, err := happydns.NewIdentifierFromString(string(c.Param("pid")))
if err != nil {
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": fmt.Sprintf("Invalid provider id: %s", err.Error())})
return
@ -224,7 +223,7 @@ func deleteProvider(c *gin.Context) {
}
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."})
return
}

View File

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

View File

@ -33,7 +33,7 @@ package api
import (
"bytes"
"encoding/hex"
"encoding/base64"
"fmt"
"log"
"net/http"
@ -356,7 +356,7 @@ func deleteUser(opts *config.Options, c *gin.Context) {
}
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 {
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) {
uid, err := hex.DecodeString(c.Param("uid"))
uid, err := base64.RawURLEncoding.DecodeString(c.Param("uid"))
if err != nil {
return nil, fmt.Errorf("Invalid user identifier given: %w", err)
}

View File

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

View File

@ -32,6 +32,7 @@
package config
import (
"encoding/base64"
"net/url"
"git.happydns.org/happydomain/model"
@ -40,11 +41,11 @@ import (
// GetAccountRecoveryURL returns the absolute URL corresponding to the recovery
// URL of the given account.
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
// validation page of the given account.
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.
type Domain struct {
// 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 HexaString `json:"id_owner"`
IdUser Identifier `json:"id_owner"`
// IsProvider is the identifier of the Provider used to access and edit the
// Domain.
IdProvider int64 `json:"id_provider"`
IdProvider Identifier `json:"id_provider"`
// DomainName is the FQDN of the managed Domain.
DomainName string `json:"domain"`
@ -55,7 +55,7 @@ type Domain struct {
// ZoneHistory are the identifiers to the Zone attached to the current
// Domain.
ZoneHistory []int64 `json:"zone_history"`
ZoneHistory []Identifier `json:"zone_history"`
}
// 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
// history.
func (d *Domain) HasZone(zoneId int64) (found bool) {
func (d *Domain) HasZone(zoneId Identifier) (found bool) {
for _, v := range d.ZoneHistory {
if v == zoneId {
if v.Equals(zoneId) {
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"`
// 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 HexaString `json:"_ownerid"`
OwnerId Identifier `json:"_ownerid"`
// Comment is a string that helps user to distinguish the Provider.
Comment string `json:"_comment,omitempty"`

View File

@ -57,10 +57,10 @@ type ServiceMeta struct {
Type string `json:"_svctype"`
// 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 HexaString `json:"_ownerid,omitempty"`
OwnerId Identifier `json:"_ownerid,omitempty"`
// Domain contains the abstract domain where this Service relates.
Domain string `json:"_domain"`

View File

@ -42,10 +42,10 @@ import (
// Session holds informatin about a User's currently connected.
type Session struct {
// Id is the Session's identifier.
Id []byte `json:"id"`
Id Identifier `json:"id"`
// 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 time.Time `json:"time"`

View File

@ -63,10 +63,10 @@ type SourceMeta struct {
Type string `json:"_srctype"`
// 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 []byte `json:"_ownerid"`
OwnerId Identifier `json:"_ownerid"`
// Comment is a string that helps user to distinguish the Source.
Comment string `json:"_comment,omitempty"`

View File

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

View File

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

View File

@ -42,10 +42,10 @@ import (
// ZoneMeta holds the metadata associated to a Zone.
type ZoneMeta struct {
// 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 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 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)
// 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(email string) (*happydns.UserAuth, error)
@ -77,7 +77,7 @@ type Storage interface {
GetDomains(u *happydns.User) (happydns.Domains, error)
// 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(u *happydns.User, dn string) (*happydns.Domain, error)
@ -106,10 +106,10 @@ type Storage interface {
GetProviderMetas(u *happydns.User) ([]happydns.ProviderMeta, error)
// 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(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(u *happydns.User, s happydns.Provider, comment string) (*happydns.ProviderCombined, error)
@ -129,7 +129,7 @@ type Storage interface {
// SESSIONS ---------------------------------------------------
// 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(user *happydns.UserAuth) ([]*happydns.Session, error)
@ -155,7 +155,7 @@ type Storage interface {
GetUsers() (happydns.Users, error)
// 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(email string) (*happydns.User, error)
@ -175,10 +175,10 @@ type Storage interface {
// ZONES ------------------------------------------------------
// 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(id int64) (*happydns.Zone, error)
GetZone(id happydns.Identifier) (*happydns.Zone, error)
// CreateZone creates a record in the database for the given Zone.
CreateZone(zone *happydns.Zone) error

View File

@ -62,9 +62,9 @@ func (s *LevelDBStorage) GetAuthUsers() (users happydns.UserAuths, err error) {
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{}
err = s.get(fmt.Sprintf("auth-%x", id), &u)
err = s.get(fmt.Sprintf("auth-%s", id.String()), &u)
return
}
@ -102,7 +102,7 @@ func (s *LevelDBStorage) AuthUserExists(email string) bool {
}
func (s *LevelDBStorage) CreateAuthUser(u *happydns.UserAuth) error {
key, id, err := s.findBytesKey("auth-", 16)
key, id, err := s.findIdentifierKey("auth-")
if err != nil {
return err
}
@ -112,11 +112,11 @@ func (s *LevelDBStorage) CreateAuthUser(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 {
return s.delete(fmt.Sprintf("auth-%x", u.Id))
return s.delete(fmt.Sprintf("auth-%s", u.Id.String()))
}
func (s *LevelDBStorage) ClearAuthUsers() error {

View File

@ -32,11 +32,11 @@
package database // import "happydns.org/storage/leveldb"
import (
crand "crypto/rand"
"encoding/json"
"fmt"
"log"
mrand "math/rand"
"git.happydns.org/happydomain/model"
"github.com/syndtr/goleveldb/leveldb"
"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)
}
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
for found {
// max random id is 2^53 to fit on float64 without loosing precision (JSON limitation)
id = mrand.Int63n(1 << 53)
key = fmt.Sprintf("%s%d", prefix, id)
found, err = s.db.Has([]byte(key), nil)
id, err = happydns.NewRandomIdentifier()
if err != nil {
return
}
}
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)
key = fmt.Sprintf("%s%s", prefix, id.String())
found, err = s.db.Has([]byte(key), nil)
if err != nil {

View File

@ -68,8 +68,8 @@ func (s *LevelDBStorage) getDomain(id string) (z *happydns.Domain, err error) {
return
}
func (s *LevelDBStorage) GetDomain(u *happydns.User, id int64) (z *happydns.Domain, err error) {
z, err = s.getDomain(fmt.Sprintf("domain-%d", id))
func (s *LevelDBStorage) GetDomain(u *happydns.User, id happydns.Identifier) (z *happydns.Domain, err error) {
z, err = s.getDomain(fmt.Sprintf("domain-%s", id.String()))
if err != nil {
return
@ -119,7 +119,7 @@ func (s *LevelDBStorage) DomainExists(dn string) bool {
}
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 {
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 {
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 {
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 {
return s.delete(fmt.Sprintf("domain-%d", z.Id))
return s.delete(fmt.Sprintf("domain-%s", z.Id.String()))
}
func (s *LevelDBStorage) ClearDomains() error {
@ -191,18 +191,18 @@ func (s *LevelDBStorage) TidyDomains() error {
if err == leveldb.ErrNotFound {
// Drop domain of unexistant users
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)
if err == leveldb.ErrNotFound {
// Drop domain of unexistant provider
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 {
// 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)
}

View File

@ -44,7 +44,7 @@ import (
"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
v, err = s.db.Get(id, nil)
if err != nil {
@ -77,9 +77,9 @@ func (s *LevelDBStorage) GetProviderMetas(u *happydns.User) (srcs []happydns.Pro
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
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 {
return
}
@ -98,9 +98,9 @@ func (s *LevelDBStorage) GetProviderMeta(u *happydns.User, id int64) (srcMeta *h
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
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 {
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) {
key, id, err := s.findInt63Key("provider-")
key, id, err := s.findIdentifierKey("provider-")
if err != nil {
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 {
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 {
@ -159,7 +159,7 @@ func (s *LevelDBStorage) UpdateProviderOwner(src *happydns.ProviderCombined, new
}
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 {
@ -202,13 +202,13 @@ func (s *LevelDBStorage) TidyProviders() error {
if err != nil {
// 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)
} else {
_, err = s.GetUser(srcMeta.OwnerId)
if err == leveldb.ErrNotFound {
// 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)
}
}

View File

@ -47,8 +47,8 @@ func (s *LevelDBStorage) getSession(id string) (session *happydns.Session, err e
return
}
func (s *LevelDBStorage) GetSession(id []byte) (session *happydns.Session, err error) {
return s.getSession(fmt.Sprintf("user.session-%x", id))
func (s *LevelDBStorage) GetSession(id happydns.Identifier) (session *happydns.Session, err error) {
return s.getSession(fmt.Sprintf("user.session-%s", id.String()))
}
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 {
key, id, err := s.findBytesKey("user.session-", 16)
key, id, err := s.findIdentifierKey("user.session-")
if err != nil {
return err
}
@ -97,11 +97,11 @@ func (s *LevelDBStorage) CreateSession(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 {
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 {
@ -144,13 +144,13 @@ func (s *LevelDBStorage) TidySessions() error {
if err != nil {
// 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)
} else {
_, err = s.GetUser(session.IdUser)
if err == leveldb.ErrNotFound {
// 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)
}
}

View File

@ -62,9 +62,9 @@ func (s *LevelDBStorage) GetUsers() (users happydns.Users, err error) {
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{}
err = s.get(fmt.Sprintf("user-%x", id), &u)
err = s.get(fmt.Sprintf("user-%s", id.String()), &u)
return
}
@ -102,7 +102,7 @@ func (s *LevelDBStorage) UserExists(email string) bool {
}
func (s *LevelDBStorage) CreateUser(u *happydns.User) error {
key, id, err := s.findBytesKey("user-", 16)
key, id, err := s.findIdentifierKey("user-")
if err != nil {
return err
}
@ -112,11 +112,11 @@ func (s *LevelDBStorage) CreateUser(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 {
return s.delete(fmt.Sprintf("user-%x", u.Id))
return s.delete(fmt.Sprintf("user-%s", u.Id.String()))
}
func (s *LevelDBStorage) ClearUsers() error {

View File

@ -34,7 +34,6 @@ package database
import (
"fmt"
"log"
"strconv"
"strings"
"git.happydns.org/happydomain/model"
@ -42,9 +41,9 @@ import (
"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{}
err = s.get(fmt.Sprintf("domain.zone-%d", id), &z)
err = s.get(fmt.Sprintf("domain.zone-%s", id.String()), &z)
return
}
@ -54,13 +53,13 @@ func (s *LevelDBStorage) getZoneMeta(id string) (z *happydns.ZoneMeta, err error
return
}
func (s *LevelDBStorage) GetZoneMeta(id int64) (z *happydns.ZoneMeta, err error) {
z, err = s.getZoneMeta(fmt.Sprintf("domain.zone-%d", id))
func (s *LevelDBStorage) GetZoneMeta(id happydns.Identifier) (z *happydns.ZoneMeta, err error) {
z, err = s.getZoneMeta(fmt.Sprintf("domain.zone-%s", id.String()))
return
}
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 {
return err
}
@ -70,11 +69,11 @@ func (s *LevelDBStorage) CreateZone(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 {
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 {
@ -112,7 +111,7 @@ func (s *LevelDBStorage) TidyZones() error {
iter := tx.NewIterator(util.BytesPrefix([]byte("domain-")), nil)
defer iter.Release()
var referencedZones []int64
var referencedZones []happydns.Identifier
for iter.Next() {
domain, _ := s.getDomain(string(iter.Key()))
@ -128,14 +127,14 @@ func (s *LevelDBStorage) TidyZones() error {
defer iter.Release()
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
log.Printf("Deleting unindentified zone: key=%s\n", iter.Key())
err = tx.Delete(iter.Key(), nil)
} else {
foundZone := false
for _, zid := range referencedZones {
if zid == zoneId {
if zid.Equals(zoneId) {
foundZone = true
break
}
@ -143,7 +142,7 @@ func (s *LevelDBStorage) TidyZones() error {
if !foundZone {
// 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)
}
}