Change primary keys and remove id column

This commit is contained in:
Melon 2025-01-08 01:03:05 +00:00
parent 2193c44252
commit fbe0863d36
Signed by: melon
GPG Key ID: 6C9D970C50D26A25
7 changed files with 234 additions and 18 deletions

View File

@ -2,6 +2,8 @@ package api
import (
"context"
"crypto/rand"
"encoding/hex"
"encoding/json"
"github.com/1f349/bluebell/database"
"github.com/1f349/bluebell/upload"
@ -14,18 +16,95 @@ import (
)
type apiDB interface {
SetDomainBranchEnabled(ctx context.Context, arg database.SetDomainBranchEnabledParams) error
AddSite(ctx context.Context, arg database.AddSiteParams) error
UpdateSiteToken(ctx context.Context, arg database.UpdateSiteTokenParams) error
SetBranchEnabled(ctx context.Context, arg database.SetBranchEnabledParams) error
}
func New(upload *upload.Handler, keyStore *mjwt.KeyStore, db apiDB) *httprouter.Router {
router := httprouter.New()
// Site upload endpoint
router.POST("/u/:site/:branch", upload.Handle)
// Site creation endpoint
router.PUT("/sites/:host", checkAuth(keyStore, func(rw http.ResponseWriter, req *http.Request, params httprouter.Params, b AuthClaims) {
host := params.ByName("host")
if !validation.IsValidSite(host) {
http.Error(rw, "Invalid site", http.StatusBadRequest)
return
}
if !validateDomainOwnershipClaims(host, b.Claims.Perms) {
http.Error(rw, "Forbidden", http.StatusForbidden)
return
}
token, err := generateToken()
if err != nil {
http.Error(rw, "Failed to generate token", http.StatusInternalServerError)
return
}
err = db.AddSite(req.Context(), database.AddSiteParams{
Domain: host,
Token: token,
})
if err != nil {
http.Error(rw, "Failed to register site", http.StatusInternalServerError)
return
}
rw.WriteHeader(http.StatusOK)
_ = json.NewEncoder(rw).Encode(struct {
Token string `json:"token"`
}{Token: token})
}))
// Reset site token endpoint
router.POST("/sites/:host/reset-token", checkAuth(keyStore, func(rw http.ResponseWriter, req *http.Request, params httprouter.Params, b AuthClaims) {
host := params.ByName("host")
if !validation.IsValidSite(host) {
http.Error(rw, "Invalid site", http.StatusBadRequest)
return
}
if !validateDomainOwnershipClaims(host, b.Claims.Perms) {
http.Error(rw, "Forbidden", http.StatusForbidden)
return
}
token, err := generateToken()
if err != nil {
http.Error(rw, "Failed to generate token", http.StatusInternalServerError)
return
}
err = db.UpdateSiteToken(req.Context(), database.UpdateSiteTokenParams{
Domain: host,
Token: token,
})
if err != nil {
http.Error(rw, "Failed to register site", http.StatusInternalServerError)
return
}
rw.WriteHeader(http.StatusOK)
_ = json.NewEncoder(rw).Encode(struct {
Token string `json:"token"`
}{Token: token})
}))
// Enable/disable site branch
router.PUT("/sites/:host/:branch/enable", checkAuth(keyStore, func(rw http.ResponseWriter, req *http.Request, params httprouter.Params, b AuthClaims) {
setEnabled(rw, req, params, b, db, true)
}))
router.DELETE("/sites/:host/:branch/enable", checkAuth(keyStore, func(rw http.ResponseWriter, req *http.Request, params httprouter.Params, b AuthClaims) {
setEnabled(rw, req, params, b, db, false)
}))
return router
}
@ -48,7 +127,7 @@ func setEnabled(rw http.ResponseWriter, req *http.Request, params httprouter.Par
return
}
err := db.SetDomainBranchEnabled(req.Context(), database.SetDomainBranchEnabledParams{
err := db.SetBranchEnabled(req.Context(), database.SetBranchEnabledParams{
Domain: host,
Branch: branch,
Enable: enable,
@ -57,7 +136,17 @@ func setEnabled(rw http.ResponseWriter, req *http.Request, params httprouter.Par
http.Error(rw, "Failed to update branch state", http.StatusInternalServerError)
return
}
rw.WriteHeader(http.StatusAccepted)
rw.WriteHeader(http.StatusOK)
}
func generateToken() (string, error) {
b := make([]byte, 32)
_, err := rand.Read(b)
if err != nil {
return "", err
}
return hex.EncodeToString(b), nil
}
// apiError outputs a generic JSON error message

View File

@ -0,0 +1,30 @@
ALTER TABLE sites RENAME TO sites_new;
ALTER TABLE branches RENAME TO branches_new;
CREATE TABLE sites
(
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
domain TEXT NOT NULL,
token TEXT NOT NULL
);
CREATE TABLE branches
(
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
domain TEXT NOT NULL,
branch TEXT NOT NULL,
last_update DATETIME NOT NULL,
enable BOOLEAN NOT NULL
);
INSERT INTO sites (domain, token)
SELECT domain, token
FROM sites_new;
INSERT INTO branches (domain, branch, last_update, enable)
SELECT domain, branch, last_update, enable
FROM branches_new;
DROP TABLE sites_new;
DROP TABLE branches_new;

View File

@ -0,0 +1,29 @@
ALTER TABLE sites RENAME TO sites_old;
ALTER TABLE branches RENAME TO branches_old;
CREATE TABLE sites
(
domain TEXT NOT NULL PRIMARY KEY,
token TEXT NOT NULL
);
CREATE TABLE branches
(
domain TEXT NOT NULL,
branch TEXT NOT NULL,
last_update DATETIME NOT NULL,
enable BOOLEAN NOT NULL,
PRIMARY KEY (domain, branch)
);
INSERT INTO sites
SELECT domain, token
FROM sites_old;
INSERT INTO branches
SELECT domain, branch, last_update, enable
FROM branches_old;
DROP TABLE sites_old;
DROP TABLE branches_old;

View File

@ -9,7 +9,6 @@ import (
)
type Branch struct {
ID int64 `json:"id"`
Domain string `json:"domain"`
Branch string `json:"branch"`
LastUpdate time.Time `json:"last_update"`
@ -17,7 +16,6 @@ type Branch struct {
}
type Site struct {
ID int64 `json:"id"`
Domain string `json:"domain"`
Token string `json:"token"`
}

View File

@ -12,11 +12,26 @@ WHERE domain = ?
AND enable = true
LIMIT 1;
-- name: AddSiteDomain :exec
-- name: AddSite :exec
INSERT INTO sites (domain, token)
VALUES (?, ?);
-- name: SetDomainBranchEnabled :exec
-- name: UpdateSiteToken :exec
UPDATE sites
SET token = ?
WHERE domain = ?;
-- name: AddBranch :exec
INSERT INTO branches (domain, branch, last_update, enable)
VALUES (?, ?, ?, ?);
-- name: UpdateBranch :exec
UPDATE branches
SET last_update = ?
WHERE domain = ?
AND branch = ?;
-- name: SetBranchEnabled :exec
UPDATE branches
SET enable = ?
WHERE domain = ?

View File

@ -10,18 +10,40 @@ import (
"time"
)
const addSiteDomain = `-- name: AddSiteDomain :exec
const addBranch = `-- name: AddBranch :exec
INSERT INTO branches (domain, branch, last_update, enable)
VALUES (?, ?, ?, ?)
`
type AddBranchParams struct {
Domain string `json:"domain"`
Branch string `json:"branch"`
LastUpdate time.Time `json:"last_update"`
Enable bool `json:"enable"`
}
func (q *Queries) AddBranch(ctx context.Context, arg AddBranchParams) error {
_, err := q.db.ExecContext(ctx, addBranch,
arg.Domain,
arg.Branch,
arg.LastUpdate,
arg.Enable,
)
return err
}
const addSite = `-- name: AddSite :exec
INSERT INTO sites (domain, token)
VALUES (?, ?)
`
type AddSiteDomainParams struct {
type AddSiteParams struct {
Domain string `json:"domain"`
Token string `json:"token"`
}
func (q *Queries) AddSiteDomain(ctx context.Context, arg AddSiteDomainParams) error {
_, err := q.db.ExecContext(ctx, addSiteDomain, arg.Domain, arg.Token)
func (q *Queries) AddSite(ctx context.Context, arg AddSiteParams) error {
_, err := q.db.ExecContext(ctx, addSite, arg.Domain, arg.Token)
return err
}
@ -47,7 +69,7 @@ func (q *Queries) GetLastUpdatedByDomainBranch(ctx context.Context, arg GetLastU
}
const getSiteByDomain = `-- name: GetSiteByDomain :one
SELECT id, domain, token
SELECT domain, token
FROM sites
WHERE domain = ?
LIMIT 1
@ -56,24 +78,58 @@ LIMIT 1
func (q *Queries) GetSiteByDomain(ctx context.Context, domain string) (Site, error) {
row := q.db.QueryRowContext(ctx, getSiteByDomain, domain)
var i Site
err := row.Scan(&i.ID, &i.Domain, &i.Token)
err := row.Scan(&i.Domain, &i.Token)
return i, err
}
const setDomainBranchEnabled = `-- name: SetDomainBranchEnabled :exec
const setBranchEnabled = `-- name: SetBranchEnabled :exec
UPDATE branches
SET enable = ?
WHERE domain = ?
AND branch = ?
`
type SetDomainBranchEnabledParams struct {
type SetBranchEnabledParams struct {
Enable bool `json:"enable"`
Domain string `json:"domain"`
Branch string `json:"branch"`
}
func (q *Queries) SetDomainBranchEnabled(ctx context.Context, arg SetDomainBranchEnabledParams) error {
_, err := q.db.ExecContext(ctx, setDomainBranchEnabled, arg.Enable, arg.Domain, arg.Branch)
func (q *Queries) SetBranchEnabled(ctx context.Context, arg SetBranchEnabledParams) error {
_, err := q.db.ExecContext(ctx, setBranchEnabled, arg.Enable, arg.Domain, arg.Branch)
return err
}
const updateBranch = `-- name: UpdateBranch :exec
UPDATE branches
SET last_update = ?
WHERE domain = ?
AND branch = ?
`
type UpdateBranchParams struct {
LastUpdate time.Time `json:"last_update"`
Domain string `json:"domain"`
Branch string `json:"branch"`
}
func (q *Queries) UpdateBranch(ctx context.Context, arg UpdateBranchParams) error {
_, err := q.db.ExecContext(ctx, updateBranch, arg.LastUpdate, arg.Domain, arg.Branch)
return err
}
const updateSiteToken = `-- name: UpdateSiteToken :exec
UPDATE sites
SET token = ?
WHERE domain = ?
`
type UpdateSiteTokenParams struct {
Token string `json:"token"`
Domain string `json:"domain"`
}
func (q *Queries) UpdateSiteToken(ctx context.Context, arg UpdateSiteTokenParams) error {
_, err := q.db.ExecContext(ctx, updateSiteToken, arg.Token, arg.Domain)
return err
}

View File

@ -48,7 +48,6 @@ type fakeUploadDB struct {
func (f *fakeUploadDB) GetSiteByDomain(_ context.Context, domain string) (database.Site, error) {
if domain == "example.com" {
return database.Site{
ID: 1,
Domain: "example.com",
Token: "abcd1234",
}, nil