mirror of
https://github.com/balzack/databag.git
synced 2025-02-12 03:29:16 +00:00
testing node configuration
This commit is contained in:
parent
000d98d934
commit
9debd23bf2
@ -124,11 +124,6 @@ paths:
|
|||||||
description: permission denide
|
description: permission denide
|
||||||
'500':
|
'500':
|
||||||
description: internal server error
|
description: internal server error
|
||||||
requestBody:
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
$ref: '#/components/schemas/NodeConfig'
|
|
||||||
|
|
||||||
/admin/accounts:
|
/admin/accounts:
|
||||||
get:
|
get:
|
||||||
@ -3595,6 +3590,10 @@ components:
|
|||||||
|
|
||||||
NodeConfig:
|
NodeConfig:
|
||||||
type: object
|
type: object
|
||||||
|
required:
|
||||||
|
- domain
|
||||||
|
- publicLimit
|
||||||
|
- accountStorage
|
||||||
properties:
|
properties:
|
||||||
domain:
|
domain:
|
||||||
type: string
|
type: string
|
||||||
|
@ -7,6 +7,7 @@ require (
|
|||||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||||
github.com/jinzhu/now v1.1.3 // indirect
|
github.com/jinzhu/now v1.1.3 // indirect
|
||||||
github.com/mattn/go-sqlite3 v1.14.9 // indirect
|
github.com/mattn/go-sqlite3 v1.14.9 // indirect
|
||||||
|
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 // indirect
|
||||||
gorm.io/driver/sqlite v1.2.6 // indirect
|
gorm.io/driver/sqlite v1.2.6 // indirect
|
||||||
gorm.io/gorm v1.22.4 // indirect
|
gorm.io/gorm v1.22.4 // indirect
|
||||||
)
|
)
|
||||||
|
@ -12,6 +12,8 @@ github.com/mattn/go-sqlite3 v1.14.9/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A
|
|||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
|
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 h1:0es+/5331RGQPcXlMfP+WrnIIS6dNnNRe0WB02W0F4M=
|
||||||
|
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gorm.io/driver/sqlite v1.2.6 h1:SStaH/b+280M7C8vXeZLz/zo9cLQmIGwwj3cSj7p6l4=
|
gorm.io/driver/sqlite v1.2.6 h1:SStaH/b+280M7C8vXeZLz/zo9cLQmIGwwj3cSj7p6l4=
|
||||||
|
@ -10,10 +10,12 @@
|
|||||||
package databag
|
package databag
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"log"
|
||||||
|
"encoding/json"
|
||||||
"net/http"
|
"net/http"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
store "databag/internal/store"
|
"golang.org/x/crypto/bcrypt"
|
||||||
|
"databag/internal/store"
|
||||||
)
|
)
|
||||||
|
|
||||||
func AddNodeAccount(w http.ResponseWriter, r *http.Request) {
|
func AddNodeAccount(w http.ResponseWriter, r *http.Request) {
|
||||||
@ -32,14 +34,11 @@ func GetNodeAccounts(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func GetNodeClaimable(w http.ResponseWriter, r *http.Request) {
|
func GetNodeClaimable(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
|
|
||||||
|
|
||||||
var config store.Config
|
if _configured {
|
||||||
err := store.DB.Where("config_id = ?", CONFIG_CLAIMED).First(&config).Error;
|
|
||||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
||||||
w.WriteHeader(http.StatusOK)
|
|
||||||
} else {
|
|
||||||
w.WriteHeader(http.StatusNotAcceptable)
|
w.WriteHeader(http.StatusNotAcceptable)
|
||||||
|
} else {
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,11 +58,97 @@ func SetNodeAccount(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func SetNodeClaim(w http.ResponseWriter, r *http.Request) {
|
func SetNodeClaim(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
|
|
||||||
|
// confirm node is claimable
|
||||||
|
if _configured {
|
||||||
|
w.WriteHeader(http.StatusUnauthorized)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// extract credentials
|
||||||
|
username, password, ok := r.BasicAuth();
|
||||||
|
if !ok {
|
||||||
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("SetNodeClaim - failed to hash password");
|
||||||
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// store credentials
|
||||||
|
err = store.DB.Transaction(func(tx *gorm.DB) error {
|
||||||
|
if res := tx.Create(&store.Config{ConfigId: CONFIG_USERNAME, StrValue: username}).Error; res != nil {
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
if res := tx.Create(&store.Config{ConfigId: CONFIG_PASSWORD, BinValue: hashedPassword}).Error; res != nil {
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
return nil;
|
||||||
|
})
|
||||||
|
if(err != nil) {
|
||||||
|
log.Printf("SetNodeCalim - failed to store credentials");
|
||||||
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// set global values
|
||||||
|
_adminUsername = username
|
||||||
|
_adminPassword = hashedPassword
|
||||||
|
|
||||||
w.WriteHeader(http.StatusOK)
|
w.WriteHeader(http.StatusOK)
|
||||||
}
|
}
|
||||||
|
|
||||||
func SetNodeConfig(w http.ResponseWriter, r *http.Request) {
|
func SetNodeConfig(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
|
|
||||||
|
// validate admin password
|
||||||
|
username, password, ok := r.BasicAuth();
|
||||||
|
if !ok {
|
||||||
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if username != _adminUsername || bcrypt.CompareHashAndPassword(_adminPassword, []byte(password)) != nil {
|
||||||
|
log.Printf("SetNodeConfig - invalid admin credentials");
|
||||||
|
w.WriteHeader(http.StatusUnauthorized);
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// parse node config
|
||||||
|
r.Body = http.MaxBytesReader(w, r.Body, CONFIG_BODYLIMIT)
|
||||||
|
dec := json.NewDecoder(r.Body)
|
||||||
|
dec.DisallowUnknownFields()
|
||||||
|
var config NodeConfig;
|
||||||
|
res := dec.Decode(&config);
|
||||||
|
if res != nil {
|
||||||
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// store credentials
|
||||||
|
err := store.DB.Transaction(func(tx *gorm.DB) error {
|
||||||
|
if res := tx.Create(&store.Config{ConfigId: CONFIG_DOMAIN, StrValue: config.Domain}).Error; res != nil {
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
if res := tx.Create(&store.Config{ConfigId: CONFIG_PUBLICLIMIT, NumValue: config.PublicLimit}).Error; res != nil {
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
if res := tx.Create(&store.Config{ConfigId: CONFIG_STORAGE, NumValue: config.AccountStorage}).Error; res != nil {
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
return nil;
|
||||||
|
})
|
||||||
|
if(err != nil) {
|
||||||
|
log.Printf("SetNodeConfig - failed to store config");
|
||||||
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// set global values
|
||||||
|
_nodeDomain = config.Domain
|
||||||
|
_publicLimit = config.PublicLimit
|
||||||
|
_accountStorage = config.AccountStorage
|
||||||
|
|
||||||
w.WriteHeader(http.StatusOK)
|
w.WriteHeader(http.StatusOK)
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
package databag
|
package databag
|
||||||
|
|
||||||
const CONFIG_CLAIMED = "claimed";
|
const CONFIG_BODYLIMIT = 1048576
|
||||||
|
|
||||||
|
const CONFIG_CONFIGURED = "configured"
|
||||||
const CONFIG_USERNAME = "username"
|
const CONFIG_USERNAME = "username"
|
||||||
const CONFIG_PASSWORD = "password"
|
const CONFIG_PASSWORD = "password"
|
||||||
const CONFIG_SATL = "salt"
|
const CONFIG_DOMAIN = "domain"
|
||||||
|
const CONFIG_PUBLICLIMIT = "public_limit"
|
||||||
|
const CONFIG_STORAGE = "storage"
|
||||||
|
50
net/server/internal/context.go
Normal file
50
net/server/internal/context.go
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
package databag
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
"databag/internal/store"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _configured bool
|
||||||
|
var _adminUsername string
|
||||||
|
var _adminPassword []byte
|
||||||
|
var _nodeDomain string
|
||||||
|
var _accountStorage int64
|
||||||
|
var _publicLimit int64
|
||||||
|
|
||||||
|
func getStrConfigValue(configId string, empty string) string {
|
||||||
|
var config store.Config
|
||||||
|
err := store.DB.Where("config_id = ?", config).First(&config).Error
|
||||||
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||||
|
return empty
|
||||||
|
}
|
||||||
|
return config.StrValue
|
||||||
|
}
|
||||||
|
|
||||||
|
func getNumConfigValue(configId string, empty int64) int64 {
|
||||||
|
var config store.Config
|
||||||
|
err := store.DB.Where("config_id = ?", config).First(&config).Error
|
||||||
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||||
|
return empty
|
||||||
|
}
|
||||||
|
return config.NumValue
|
||||||
|
}
|
||||||
|
|
||||||
|
func getBoolConfigValue(configId string, empty bool) bool {
|
||||||
|
var config store.Config
|
||||||
|
err := store.DB.Where("config_id = ?", config).First(&config).Error
|
||||||
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||||
|
return empty
|
||||||
|
}
|
||||||
|
return config.BoolValue
|
||||||
|
}
|
||||||
|
|
||||||
|
func getBinConfigValue(configId string, empty []byte) []byte {
|
||||||
|
var config store.Config
|
||||||
|
err := store.DB.Where("config_id = ?", config).First(&config).Error
|
||||||
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||||
|
return empty
|
||||||
|
}
|
||||||
|
return config.BinValue
|
||||||
|
}
|
@ -27,6 +27,14 @@ type Routes []Route
|
|||||||
|
|
||||||
func NewRouter() *mux.Router {
|
func NewRouter() *mux.Router {
|
||||||
|
|
||||||
|
// populate context
|
||||||
|
_configured = getBoolConfigValue(CONFIG_CONFIGURED, false);
|
||||||
|
_adminUsername = getStrConfigValue(CONFIG_USERNAME, "");
|
||||||
|
_adminPassword = getBinConfigValue(CONFIG_PASSWORD, nil);
|
||||||
|
_nodeDomain = getStrConfigValue(CONFIG_DOMAIN, "");
|
||||||
|
_publicLimit = getNumConfigValue(CONFIG_PUBLICLIMIT, 0);
|
||||||
|
_accountStorage = getNumConfigValue(CONFIG_STORAGE, 0);
|
||||||
|
|
||||||
router := mux.NewRouter().StrictSlash(true)
|
router := mux.NewRouter().StrictSlash(true)
|
||||||
for _, route := range routes {
|
for _, route := range routes {
|
||||||
var handler http.Handler
|
var handler http.Handler
|
||||||
|
@ -31,6 +31,7 @@ type Config struct {
|
|||||||
StrValue string
|
StrValue string
|
||||||
NumValue int64
|
NumValue int64
|
||||||
BoolValue bool
|
BoolValue bool
|
||||||
|
BinValue []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
type AccountToken struct {
|
type AccountToken struct {
|
||||||
@ -46,8 +47,7 @@ type Account struct {
|
|||||||
ID uint `gorm:"primaryKey;not null;unique;autoIncrement"`
|
ID uint `gorm:"primaryKey;not null;unique;autoIncrement"`
|
||||||
Did string `gorm:"not null"`
|
Did string `gorm:"not null"`
|
||||||
Username string `gorm:"not null;uniqueIndex"`
|
Username string `gorm:"not null;uniqueIndex"`
|
||||||
Password string `gorm:"not null"`
|
Password []byte `gorm:"not null"`
|
||||||
Salt string `gorm:"not null"`
|
|
||||||
Name string
|
Name string
|
||||||
Description string
|
Description string
|
||||||
Location string
|
Location string
|
||||||
|
@ -1,38 +1,53 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
|
"encoding/json"
|
||||||
app "databag/internal"
|
app "databag/internal"
|
||||||
store "databag/internal/store"
|
"databag/internal/store"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestSetup(t *testing.T) {
|
func TestSetup(t *testing.T) {
|
||||||
|
|
||||||
store.SetPath("file::memory:?cache=shared");
|
store.SetPath("file::memory:?cache=shared");
|
||||||
|
//store.SetPath("databag.db");
|
||||||
Claimable(t);
|
Claimable(t);
|
||||||
Claim(t);
|
Claim(t);
|
||||||
|
Config(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
func Claimable(t *testing.T) {
|
func Claimable(t *testing.T) {
|
||||||
r := httptest.NewRequest("GET", "/claimable", nil)
|
r := httptest.NewRequest("GET", "/admin/claimable", nil)
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
app.GetNodeClaimable(w, r);
|
app.GetNodeClaimable(w, r)
|
||||||
if w.Code != 200 {
|
if w.Code != 200 {
|
||||||
t.Errorf("server not initially claimable");
|
t.Errorf("server not initially claimable")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Claim(t *testing.T) {
|
func Claim(t *testing.T) {
|
||||||
auth := base64.StdEncoding.EncodeToString([]byte("admin:pass"))
|
auth := base64.StdEncoding.EncodeToString([]byte("admin:pass"))
|
||||||
r := httptest.NewRequest("GET", "/claimable", nil)
|
r := httptest.NewRequest("PUT", "/admin/claim", nil)
|
||||||
r.Header.Add("Authorization","Basic " + auth)
|
r.Header.Add("Authorization","Basic " + auth)
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
app.GetNodeClaimable(w, r);
|
app.SetNodeClaim(w, r)
|
||||||
if w.Code != 200 {
|
if w.Code != 200 {
|
||||||
t.Errorf("server not initially claimable");
|
t.Errorf("server not initially claimable")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Config(t *testing.T) {
|
||||||
|
config := app.NodeConfig{Domain: "example.com", PublicLimit: 1024, AccountStorage: 4096}
|
||||||
|
auth := base64.StdEncoding.EncodeToString([]byte("admin:pass"))
|
||||||
|
body,_ := json.Marshal(config)
|
||||||
|
r := httptest.NewRequest("PUT", "/admin/config", strings.NewReader(string(body)))
|
||||||
|
r.Header.Add("Authorization","Basic " + auth)
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
app.SetNodeConfig(w, r);
|
||||||
|
if w.Code != 200 {
|
||||||
|
t.Errorf("failed to set node config")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user