acme-dns/db.go

151 lines
3.1 KiB
Go
Raw Normal View History

2016-11-11 21:48:00 +07:00
package main
import (
"database/sql"
2016-11-13 19:50:44 +07:00
"errors"
2016-11-11 21:48:00 +07:00
_ "github.com/mattn/go-sqlite3"
2016-11-13 19:50:44 +07:00
"github.com/satori/go.uuid"
"golang.org/x/crypto/bcrypt"
2016-11-11 21:48:00 +07:00
)
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) {
2016-11-13 19:50:44 +07:00
a, err := NewACMETxt()
if err != nil {
return ACMETxt{}, err
}
password_hash, err := bcrypt.GenerateFromPassword([]byte(a.Password), 10)
2016-11-11 21:48:00 +07:00
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()
2016-11-13 19:50:44 +07:00
_, err = sm.Exec(a.Username, password_hash, a.Subdomain, a.Value)
2016-11-11 21:48:00 +07:00
if err != nil {
return a, err
}
return a, nil
}
2016-11-13 19:50:44 +07:00
func (d *Database) GetByUsername(u uuid.UUID) (ACMETxt, error) {
2016-11-11 21:48:00 +07:00
var results []ACMETxt
get_sql := `
2016-11-13 19:50:44 +07:00
SELECT Username, Password, Subdomain, Value, LastActive
2016-11-11 21:48:00 +07:00
FROM records
WHERE Username=? LIMIT 1
`
sm, err := d.DB.Prepare(get_sql)
if err != nil {
2016-11-13 19:50:44 +07:00
return ACMETxt{}, err
2016-11-11 21:48:00 +07:00
}
defer sm.Close()
2016-11-13 19:50:44 +07:00
rows, err := sm.Query(u.String())
2016-11-11 21:48:00 +07:00
if err != nil {
2016-11-13 19:50:44 +07:00
return ACMETxt{}, err
2016-11-11 21:48:00 +07:00
}
defer rows.Close()
// It will only be one row though
for rows.Next() {
var a ACMETxt = ACMETxt{}
2016-11-13 19:50:44 +07:00
var uname string
err = rows.Scan(&uname, &a.Password, &a.Subdomain, &a.Value, &a.LastActive)
if err != nil {
return ACMETxt{}, err
}
a.Username, err = uuid.FromString(uname)
2016-11-11 21:48:00 +07:00
if err != nil {
2016-11-13 19:50:44 +07:00
return ACMETxt{}, err
2016-11-11 21:48:00 +07:00
}
results = append(results, a)
}
2016-11-13 19:50:44 +07:00
if len(results) > 0 {
return results[0], nil
} else {
return ACMETxt{}, errors.New("no user")
}
2016-11-11 21:48:00 +07:00
}
func (d *Database) GetByDomain(domain string) ([]ACMETxt, error) {
2016-11-13 19:50:44 +07:00
domain = SanitizeString(domain)
2016-11-11 21:48:00 +07:00
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
}