Initial commit
This commit is contained in:
97
cmd/qddns-server/main.go
Normal file
97
cmd/qddns-server/main.go
Normal file
@@ -0,0 +1,97 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/jackc/pgx/v4/pgxpool"
|
||||
"github.com/thequux/pdns-auto-update/common"
|
||||
_ "go.uber.org/zap"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var db *pgxpool.Pool
|
||||
|
||||
func main() {
|
||||
conn, err := pgxpool.Connect(context.Background(), os.Getenv("QDDNS_DB"))
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Unabled to connect to database: %v")
|
||||
os.Exit(1)
|
||||
}
|
||||
defer conn.Close()
|
||||
db = conn
|
||||
|
||||
// Set up server
|
||||
r := gin.Default()
|
||||
r.POST("/update/:domain", func(c *gin.Context) {
|
||||
authHdr := strings.Fields(c.GetHeader("Authorization"))
|
||||
domain := c.Param("domain");
|
||||
|
||||
clientIP := c.ClientIP()
|
||||
ip := net.ParseIP(clientIP)
|
||||
var token string
|
||||
if len(authHdr) == 0 || authHdr[0] != "bearer" {
|
||||
// we have a token; check if it's valid for domain
|
||||
token = authHdr[1]
|
||||
} else {
|
||||
c.JSON(http.StatusUnauthorized, common.Response{Status: "error", Message: "Missing bearer token", Code: "QDA0001"})
|
||||
return
|
||||
}
|
||||
|
||||
if ip == nil {
|
||||
c.JSON(http.StatusBadRequest, common.Response{Status: "error", Message: "Unable to determine client IP (got " + clientIP + ")", Code: "QDE0003"})
|
||||
return
|
||||
}
|
||||
|
||||
// get a connection
|
||||
tx, err := db.Begin(c)
|
||||
defer tx.Rollback(c)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, common.Response{Status: "error", Message: "Failed to access database", Code: "QDE0001"})
|
||||
return
|
||||
}
|
||||
// check token validity
|
||||
row := tx.QueryRow(c, "SELECT COUNT(*) from qddns_auth WHERE token = $1 AND domain = $2", token, domain);
|
||||
var rcount int
|
||||
if err := row.Scan(&rcount); err != nil {
|
||||
c.JSON(http.StatusInternalServerError, common.Response{Status: "error", Message: "Failed to check token " + err.Error(), Code: "QDE0002"})
|
||||
return
|
||||
} else if rcount < 1 {
|
||||
c.JSON(http.StatusUnauthorized, common.Response{Status: "error", Message: "Not authorized for domain " + domain, Code: "QDA0002"})
|
||||
return
|
||||
}
|
||||
|
||||
// Identify the type of address
|
||||
|
||||
var recordType string
|
||||
if ip.To4() == nil {
|
||||
recordType = "AAAA"
|
||||
clientIP = ip.To16().String()
|
||||
} else {
|
||||
recordType = "A"
|
||||
clientIP = ip.To4().String()
|
||||
}
|
||||
|
||||
// Do the update
|
||||
tag, err := tx.Exec(c, "UPDATE records SET content = $1 WHERE domain = $2 AND type = $3", clientIP, domain, recordType)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, common.Response{
|
||||
Status: "error",
|
||||
Message: "Failed to update record: " + err.Error(),
|
||||
Code: "QDD0001",
|
||||
})
|
||||
return
|
||||
}
|
||||
if tag.RowsAffected() != 1 {
|
||||
c.JSON(http.StatusInternalServerError, common.Response{
|
||||
Status: "error",
|
||||
Message: "Wrong number of rows affected: " + string(tag.RowsAffected()),
|
||||
})
|
||||
return
|
||||
}
|
||||
tx.Commit(c)
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user