acme-dns/db.go

181 lines
3.8 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-17 22:52:55 +07:00
_ "github.com/lib/pq"
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-17 22:52:55 +07:00
"regexp"
"time"
2016-11-11 21:48:00 +07:00
)
2016-11-23 23:07:38 +07:00
type database struct {
2016-11-11 21:48:00 +07:00
DB *sql.DB
}
2016-11-17 00:15:36 +07:00
var recordsTable = `
2016-11-11 21:48:00 +07:00
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,
2016-11-17 22:52:55 +07:00
LastActive INT
2016-11-11 21:48:00 +07:00
);`
2016-11-17 22:52:55 +07:00
// getSQLiteStmt replaces all PostgreSQL prepared statement placeholders (eg. $1, $2) with SQLite variant "?"
func getSQLiteStmt(s string) string {
re, err := regexp.Compile("\\$[0-9]")
if err != nil {
log.Errorf("%v", err)
return s
}
return re.ReplaceAllString(s, "?")
}
2016-11-23 23:07:38 +07:00
func (d *database) Init(engine string, connection string) error {
2016-11-17 22:52:55 +07:00
db, err := sql.Open(engine, connection)
2016-11-11 21:48:00 +07:00
if err != nil {
return err
}
d.DB = db
2016-11-18 17:09:43 +07:00
d.DB.SetMaxOpenConns(1)
2016-11-17 00:15:36 +07:00
_, err = d.DB.Exec(recordsTable)
2016-11-11 21:48:00 +07:00
if err != nil {
return err
}
return nil
}
2016-11-23 23:07:38 +07:00
func (d *database) Register() (ACMETxt, error) {
2016-11-23 22:11:31 +07:00
a, err := newACMETxt()
2016-11-13 19:50:44 +07:00
if err != nil {
return ACMETxt{}, err
}
2016-11-17 00:15:36 +07:00
passwordHash, err := bcrypt.GenerateFromPassword([]byte(a.Password), 10)
2016-11-17 22:52:55 +07:00
timenow := time.Now().Unix()
2016-11-17 00:15:36 +07:00
regSQL := `
2016-11-11 21:48:00 +07:00
INSERT INTO records(
Username,
Password,
Subdomain,
2016-11-17 22:52:55 +07:00
Value,
LastActive)
values($1, $2, $3, '', $4)`
if DNSConf.Database.Engine == "sqlite3" {
regSQL = getSQLiteStmt(regSQL)
}
2016-11-17 00:15:36 +07:00
sm, err := d.DB.Prepare(regSQL)
2016-11-11 21:48:00 +07:00
if err != nil {
return a, errors.New("SQL error")
2016-11-11 21:48:00 +07:00
}
defer sm.Close()
2016-11-17 22:52:55 +07:00
_, err = sm.Exec(a.Username.String(), passwordHash, a.Subdomain, timenow)
2016-11-11 21:48:00 +07:00
if err != nil {
return a, err
}
return a, nil
}
2016-11-23 23:07:38 +07:00
func (d *database) GetByUsername(u uuid.UUID) (ACMETxt, error) {
2016-11-11 21:48:00 +07:00
var results []ACMETxt
2016-11-17 00:15:36 +07:00
getSQL := `
2016-11-13 19:50:44 +07:00
SELECT Username, Password, Subdomain, Value, LastActive
2016-11-11 21:48:00 +07:00
FROM records
2016-11-17 22:52:55 +07:00
WHERE Username=$1 LIMIT 1
2016-11-11 21:48:00 +07:00
`
2016-11-17 22:52:55 +07:00
if DNSConf.Database.Engine == "sqlite3" {
getSQL = getSQLiteStmt(getSQL)
}
2016-11-17 00:15:36 +07:00
sm, err := d.DB.Prepare(getSQL)
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 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() {
2016-11-17 00:15:36 +07:00
a := 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
}
2016-11-17 00:15:36 +07:00
return ACMETxt{}, errors.New("no user")
2016-11-11 21:48:00 +07:00
}
2016-11-23 23:07:38 +07:00
func (d *database) GetByDomain(domain string) ([]ACMETxt, error) {
2016-11-23 22:11:31 +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
2016-11-17 00:15:36 +07:00
getSQL := `
2016-11-11 21:48:00 +07:00
SELECT Username, Password, Subdomain, Value
FROM records
2016-11-17 22:52:55 +07:00
WHERE Subdomain=$1 LIMIT 1
2016-11-11 21:48:00 +07:00
`
2016-11-17 22:52:55 +07:00
if DNSConf.Database.Engine == "sqlite3" {
getSQL = getSQLiteStmt(getSQL)
}
2016-11-17 00:15:36 +07:00
sm, err := d.DB.Prepare(getSQL)
2016-11-11 21:48:00 +07:00
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
}
2016-11-23 23:07:38 +07:00
func (d *database) Update(a ACMETxt) error {
2016-11-11 21:48:00 +07:00
// Data in a is already sanitized
log.Debugf("Trying to update domain [%s] with TXT data [%s]", a.Subdomain, a.Value)
2016-11-17 22:52:55 +07:00
timenow := time.Now().Unix()
2016-11-17 00:15:36 +07:00
updSQL := `
2016-11-17 22:52:55 +07:00
UPDATE records SET Value=$1, LastActive=$2
WHERE Username=$3 AND Subdomain=$4
2016-11-11 21:48:00 +07:00
`
2016-11-17 22:52:55 +07:00
if DNSConf.Database.Engine == "sqlite3" {
updSQL = getSQLiteStmt(updSQL)
}
2016-11-17 00:15:36 +07:00
sm, err := d.DB.Prepare(updSQL)
2016-11-11 21:48:00 +07:00
if err != nil {
return err
}
defer sm.Close()
2016-11-17 22:52:55 +07:00
_, err = sm.Exec(a.Value, timenow, a.Username, a.Subdomain)
2016-11-11 21:48:00 +07:00
if err != nil {
return err
}
return nil
}