mirror of
https://github.com/joohoi/acme-dns.git
synced 2025-01-05 13:08:06 +07:00
190 lines
3.8 KiB
Go
190 lines
3.8 KiB
Go
|
package main
|
|||
|
|
|||
|
import (
|
|||
|
"database/sql"
|
|||
|
//"encoding/json"
|
|||
|
//"github.com/boltdb/bolt"
|
|||
|
_ "github.com/mattn/go-sqlite3"
|
|||
|
//"strings"
|
|||
|
)
|
|||
|
|
|||
|
type Database struct {
|
|||
|
DB *sql.DB
|
|||
|
}
|
|||
|
|
|||
|
var records_table string = `
|
|||
|
CREATE TABLE IF NOT EXISTS records(
|
|||
|
Username TEXT UNIQUE NOT NULL PRIMARY KEY,
|
|||
|
Password TEXT UNIQUE NOT NULL,
|
|||
|
Subdomain TEXT UNIQUE NOT NULL,
|
|||
|
Value TEXT,
|
|||
|
LastActive DATETIME
|
|||
|
);`
|
|||
|
|
|||
|
func (d *Database) Init(filename string) error {
|
|||
|
db, err := sql.Open("sqlite3", filename)
|
|||
|
if err != nil {
|
|||
|
return err
|
|||
|
}
|
|||
|
d.DB = db
|
|||
|
_, err = d.DB.Exec(records_table)
|
|||
|
if err != nil {
|
|||
|
return err
|
|||
|
}
|
|||
|
return nil
|
|||
|
}
|
|||
|
|
|||
|
func (d *Database) Register() (ACMETxt, error) {
|
|||
|
a := NewACMETxt()
|
|||
|
reg_sql := `
|
|||
|
INSERT INTO records(
|
|||
|
Username,
|
|||
|
Password,
|
|||
|
Subdomain,
|
|||
|
Value,
|
|||
|
LastActive)
|
|||
|
values(?, ?, ?, ?, CURRENT_TIMESTAMP)`
|
|||
|
sm, err := d.DB.Prepare(reg_sql)
|
|||
|
if err != nil {
|
|||
|
return a, err
|
|||
|
}
|
|||
|
defer sm.Close()
|
|||
|
_, err = sm.Exec(a.Username, a.Password, a.Subdomain, a.Value)
|
|||
|
if err != nil {
|
|||
|
return a, err
|
|||
|
}
|
|||
|
// Do an insert check
|
|||
|
/*
|
|||
|
id, err := status.LastInsertId()
|
|||
|
if err != nil {
|
|||
|
return a, err
|
|||
|
}*/
|
|||
|
|
|||
|
return a, nil
|
|||
|
}
|
|||
|
|
|||
|
func (d *Database) GetByUsername(u string) ([]ACMETxt, error) {
|
|||
|
u = NormalizeString(u, 36)
|
|||
|
log.Debugf("Trying to select by user [%s] from table", u)
|
|||
|
var results []ACMETxt
|
|||
|
get_sql := `
|
|||
|
SELECT Username, Password, Subdomain, Value
|
|||
|
FROM records
|
|||
|
WHERE Username=? LIMIT 1
|
|||
|
`
|
|||
|
sm, err := d.DB.Prepare(get_sql)
|
|||
|
if err != nil {
|
|||
|
return nil, err
|
|||
|
}
|
|||
|
defer sm.Close()
|
|||
|
rows, err := sm.Query(u)
|
|||
|
if err != nil {
|
|||
|
return nil, err
|
|||
|
}
|
|||
|
defer rows.Close()
|
|||
|
|
|||
|
// It will only be one row though
|
|||
|
for rows.Next() {
|
|||
|
var a ACMETxt = ACMETxt{}
|
|||
|
err = rows.Scan(&a.Username, &a.Password, &a.Subdomain, &a.Value)
|
|||
|
if err != nil {
|
|||
|
return nil, err
|
|||
|
}
|
|||
|
results = append(results, a)
|
|||
|
}
|
|||
|
return results, nil
|
|||
|
}
|
|||
|
|
|||
|
func (d *Database) GetByDomain(domain string) ([]ACMETxt, error) {
|
|||
|
domain = NormalizeString(domain, 36)
|
|||
|
log.Debugf("Trying to select domain [%s] from table", domain)
|
|||
|
var a []ACMETxt
|
|||
|
get_sql := `
|
|||
|
SELECT Username, Password, Subdomain, Value
|
|||
|
FROM records
|
|||
|
WHERE Subdomain=? LIMIT 1
|
|||
|
`
|
|||
|
sm, err := d.DB.Prepare(get_sql)
|
|||
|
if err != nil {
|
|||
|
return a, err
|
|||
|
}
|
|||
|
defer sm.Close()
|
|||
|
rows, err := sm.Query(domain)
|
|||
|
if err != nil {
|
|||
|
return a, err
|
|||
|
}
|
|||
|
defer rows.Close()
|
|||
|
|
|||
|
for rows.Next() {
|
|||
|
txt := ACMETxt{}
|
|||
|
err = rows.Scan(&txt.Username, &txt.Password, &txt.Subdomain, &txt.Value)
|
|||
|
if err != nil {
|
|||
|
return a, err
|
|||
|
}
|
|||
|
a = append(a, txt)
|
|||
|
}
|
|||
|
return a, nil
|
|||
|
}
|
|||
|
|
|||
|
func (d *Database) Update(a ACMETxt) error {
|
|||
|
// Data in a is already sanitized
|
|||
|
log.Debugf("Trying to update domain [%s] with TXT data [%s]", a.Subdomain, a.Value)
|
|||
|
upd_sql := `
|
|||
|
UPDATE records SET Value=?
|
|||
|
WHERE Username=? AND Subdomain=?
|
|||
|
`
|
|||
|
sm, err := d.DB.Prepare(upd_sql)
|
|||
|
if err != nil {
|
|||
|
return err
|
|||
|
}
|
|||
|
defer sm.Close()
|
|||
|
_, err = sm.Exec(a.Value, a.Username, a.Subdomain)
|
|||
|
if err != nil {
|
|||
|
return err
|
|||
|
}
|
|||
|
return nil
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
func addTXT(txt ACMETxt) error {
|
|||
|
|
|||
|
err := db.Update(func(tx *bolt.Tx) error {
|
|||
|
bucket, err := tx.CreateBucketIfNotExists([]byte("domains"))
|
|||
|
if err != nil {
|
|||
|
return err
|
|||
|
}
|
|||
|
jtxt, err := json.Marshal(txt)
|
|||
|
if err != nil {
|
|||
|
return err
|
|||
|
}
|
|||
|
|
|||
|
// put returns nil if successful, nil return commits db.Update
|
|||
|
return bucket.Put([]byte(strings.ToLower(txt.Domain)), jtxt)
|
|||
|
})
|
|||
|
return err
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
func getTXT(domain string) (ACMETxt, error) {
|
|||
|
var atxt ACMETxt
|
|||
|
err := db.View(func(tx *bolt.Tx) error {
|
|||
|
bucket := tx.Bucket([]byte("domains"))
|
|||
|
value := bucket.Get([]byte(strings.ToLower(domain)))
|
|||
|
if len(value) == 0 {
|
|||
|
// Not found
|
|||
|
log.Debugf("Record for [%s] not found", domain)
|
|||
|
atxt = ACMETxt{}
|
|||
|
} else {
|
|||
|
if err := json.Unmarshal(value, &atxt); err != nil {
|
|||
|
return err
|
|||
|
}
|
|||
|
}
|
|||
|
return nil
|
|||
|
})
|
|||
|
if err != nil {
|
|||
|
return ACMETxt{}, err
|
|||
|
}
|
|||
|
return atxt, err
|
|||
|
}
|
|||
|
*/
|