mirror of
https://github.com/balzack/databag.git
synced 2025-02-12 03:29:16 +00:00
added addAccount endpoint
This commit is contained in:
parent
a5a02d7abb
commit
1c3518424a
16
doc/api.oa3
16
doc/api.oa3
@ -75,7 +75,7 @@ paths:
|
|||||||
description: Set admin password and node domain
|
description: Set admin password and node domain
|
||||||
operationId: set-node-claim
|
operationId: set-node-claim
|
||||||
security:
|
security:
|
||||||
- basicAuth: []
|
- basicCredentials: []
|
||||||
parameters:
|
parameters:
|
||||||
- name: domain
|
- name: domain
|
||||||
in: query
|
in: query
|
||||||
@ -302,7 +302,7 @@ paths:
|
|||||||
operationId: add-public-account
|
operationId: add-public-account
|
||||||
security:
|
security:
|
||||||
- bearerAuth: []
|
- bearerAuth: []
|
||||||
- basicAuth: []
|
- basicCredentials: []
|
||||||
responses:
|
responses:
|
||||||
'201':
|
'201':
|
||||||
description: successful operation
|
description: successful operation
|
||||||
@ -431,7 +431,7 @@ paths:
|
|||||||
operationId: add-account
|
operationId: add-account
|
||||||
security:
|
security:
|
||||||
- bearerAuth: []
|
- bearerAuth: []
|
||||||
- basicAuth: []
|
- basicCredentials: []
|
||||||
responses:
|
responses:
|
||||||
'201':
|
'201':
|
||||||
description: successful operation
|
description: successful operation
|
||||||
@ -3964,11 +3964,11 @@ components:
|
|||||||
Profile:
|
Profile:
|
||||||
type: object
|
type: object
|
||||||
required:
|
required:
|
||||||
- profileId
|
- guid
|
||||||
- revision
|
- revision
|
||||||
- node
|
- node
|
||||||
properties:
|
properties:
|
||||||
profileId:
|
guid:
|
||||||
type: string
|
type: string
|
||||||
handle:
|
handle:
|
||||||
type: string
|
type: string
|
||||||
@ -4468,7 +4468,11 @@ components:
|
|||||||
basicAuth:
|
basicAuth:
|
||||||
type: http
|
type: http
|
||||||
scheme: basic
|
scheme: basic
|
||||||
|
|
||||||
|
basicCredentials:
|
||||||
|
type: http
|
||||||
|
schema
|
||||||
|
|
||||||
bearerAuth:
|
bearerAuth:
|
||||||
type: http
|
type: http
|
||||||
scheme: bearer
|
scheme: bearer
|
||||||
|
@ -7,7 +7,10 @@ require (
|
|||||||
github.com/gorilla/websocket v1.4.2 // indirect
|
github.com/gorilla/websocket v1.4.2 // indirect
|
||||||
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/kr/pretty v0.3.0 // indirect
|
||||||
|
github.com/kr/text v0.2.0 // indirect
|
||||||
github.com/mattn/go-sqlite3 v1.14.9 // indirect
|
github.com/mattn/go-sqlite3 v1.14.9 // indirect
|
||||||
|
github.com/rogpeppe/go-internal v1.6.1 // indirect
|
||||||
github.com/theckman/go-securerandom v0.1.1 // indirect
|
github.com/theckman/go-securerandom v0.1.1 // indirect
|
||||||
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 // 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
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
|
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
|
||||||
@ -9,9 +10,18 @@ github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkr
|
|||||||
github.com/jinzhu/now v1.1.2/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
github.com/jinzhu/now v1.1.2/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||||
github.com/jinzhu/now v1.1.3 h1:PlHq1bSCSZL9K0wUhbm2pGLoTWs2GwVhsP6emvGV/ZI=
|
github.com/jinzhu/now v1.1.3 h1:PlHq1bSCSZL9K0wUhbm2pGLoTWs2GwVhsP6emvGV/ZI=
|
||||||
github.com/jinzhu/now v1.1.3/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
github.com/jinzhu/now v1.1.3/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||||
|
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||||
|
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
|
||||||
|
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
|
||||||
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
|
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||||
|
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||||
github.com/mattn/go-sqlite3 v1.14.9 h1:10HX2Td0ocZpYEjhilsuo6WWtUqttj2Kb0KtD86/KYA=
|
github.com/mattn/go-sqlite3 v1.14.9 h1:10HX2Td0ocZpYEjhilsuo6WWtUqttj2Kb0KtD86/KYA=
|
||||||
github.com/mattn/go-sqlite3 v1.14.9/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
|
github.com/mattn/go-sqlite3 v1.14.9/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
|
||||||
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/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k=
|
||||||
|
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
||||||
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=
|
||||||
github.com/theckman/go-securerandom v0.1.1 h1:5KctSyM0D5KKFK+bsypIyLq7yik0CEaI5i2fGcUGcsQ=
|
github.com/theckman/go-securerandom v0.1.1 h1:5KctSyM0D5KKFK+bsypIyLq7yik0CEaI5i2fGcUGcsQ=
|
||||||
@ -19,6 +29,8 @@ github.com/theckman/go-securerandom v0.1.1/go.mod h1:bmkysLfBH6i891sBpcP4xRM3XIB
|
|||||||
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 h1:0es+/5331RGQPcXlMfP+WrnIIS6dNnNRe0WB02W0F4M=
|
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=
|
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/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||||
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=
|
||||||
gorm.io/driver/sqlite v1.2.6/go.mod h1:gyoX0vHiiwi0g49tv+x2E7l8ksauLK0U/gShcdUsjWY=
|
gorm.io/driver/sqlite v1.2.6/go.mod h1:gyoX0vHiiwi0g49tv+x2E7l8ksauLK0U/gShcdUsjWY=
|
||||||
|
77
net/server/internal/addAccount_endpoint.go
Normal file
77
net/server/internal/addAccount_endpoint.go
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
package databag
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"crypto/sha256"
|
||||||
|
"encoding/hex"
|
||||||
|
"databag/internal/store"
|
||||||
|
)
|
||||||
|
|
||||||
|
func AddAccount(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
|
if _, err := bearerAccountToken(r); err != nil {
|
||||||
|
LogMsg("authentication failed")
|
||||||
|
w.WriteHeader(http.StatusUnauthorized)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
username, password, err := basicCredentials(r);
|
||||||
|
if err != nil {
|
||||||
|
LogMsg("invalid basic credentials")
|
||||||
|
w.WriteHeader(http.StatusUnauthorized)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// generate account key
|
||||||
|
privateKey, publicKey := GenerateRsaKeyPair()
|
||||||
|
privatePem := ExportRsaPrivateKeyAsPemStr(privateKey)
|
||||||
|
publicPem, err := ExportRsaPublicKeyAsPemStr(publicKey)
|
||||||
|
if err != nil {
|
||||||
|
LogMsg("failed generate key")
|
||||||
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// compute key fingerprint
|
||||||
|
msg := []byte(publicPem)
|
||||||
|
hash := sha256.New()
|
||||||
|
if _, err = hash.Write(msg); err != nil {
|
||||||
|
LogMsg("failed to fingerprint key")
|
||||||
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fingerprint := hex.EncodeToString(hash.Sum(nil))
|
||||||
|
|
||||||
|
// create new account
|
||||||
|
account := store.Account{
|
||||||
|
PublicKey: publicPem,
|
||||||
|
PrivateKey: privatePem,
|
||||||
|
KeyType: "RSA4096",
|
||||||
|
Username: username,
|
||||||
|
Password: password,
|
||||||
|
Guid: fingerprint,
|
||||||
|
};
|
||||||
|
if res := store.DB.Create(&account).Error; res != nil {
|
||||||
|
LogMsg("failed to store account")
|
||||||
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// create response
|
||||||
|
profile := Profile{
|
||||||
|
Guid: account.Guid,
|
||||||
|
Handle: account.Username,
|
||||||
|
Name: account.Name,
|
||||||
|
Description: account.Description,
|
||||||
|
Location: account.Location,
|
||||||
|
Image: account.Image,
|
||||||
|
Revision: account.ProfileRevision,
|
||||||
|
Version: CONFIG_VERSION,
|
||||||
|
Node: "https://" + getStrConfigValue(CONFIG_DOMAIN, ""),
|
||||||
|
}
|
||||||
|
|
||||||
|
// send response
|
||||||
|
WriteResponse(w, profile)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -14,11 +14,11 @@ func TestAccount(t *testing.T) {
|
|||||||
r := httptest.NewRequest("POST", "/admin/accounts", nil)
|
r := httptest.NewRequest("POST", "/admin/accounts", nil)
|
||||||
r.Header.Add("Authorization","Basic " + auth)
|
r.Header.Add("Authorization","Basic " + auth)
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
AddNodeAccount(w, r);
|
AddNodeAccount(w, r)
|
||||||
resp := w.Result();
|
resp := w.Result()
|
||||||
dec := json.NewDecoder(resp.Body);
|
dec := json.NewDecoder(resp.Body)
|
||||||
var token string;
|
var token string
|
||||||
dec.Decode(&token);
|
dec.Decode(&token)
|
||||||
if resp.StatusCode != 200 {
|
if resp.StatusCode != 200 {
|
||||||
t.Errorf("failed to create account")
|
t.Errorf("failed to create account")
|
||||||
return
|
return
|
||||||
@ -28,36 +28,55 @@ func TestAccount(t *testing.T) {
|
|||||||
r = httptest.NewRequest("GET", "/account/token", nil)
|
r = httptest.NewRequest("GET", "/account/token", nil)
|
||||||
r.Header.Add("Authorization","Bearer " + token)
|
r.Header.Add("Authorization","Bearer " + token)
|
||||||
w = httptest.NewRecorder()
|
w = httptest.NewRecorder()
|
||||||
GetAccountToken(w, r);
|
GetAccountToken(w, r)
|
||||||
resp = w.Result();
|
resp = w.Result()
|
||||||
if resp.StatusCode != 200 {
|
if resp.StatusCode != 200 {
|
||||||
t.Errorf("invalid token value")
|
t.Errorf("invalid token value")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
dec = json.NewDecoder(resp.Body);
|
dec = json.NewDecoder(resp.Body)
|
||||||
var tokenType string;
|
var tokenType string
|
||||||
dec.Decode(&tokenType);
|
dec.Decode(&tokenType)
|
||||||
if tokenType != "create" {
|
if tokenType != "create" {
|
||||||
t.Errorf("invalid token type")
|
t.Errorf("invalid token type")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if username is available
|
// check if username is available
|
||||||
r = httptest.NewRequest("GET", "/account/claimable?username=databag", nil)
|
r = httptest.NewRequest("GET", "/account/claimable?username=user", nil)
|
||||||
r.Header.Add("Authorization","Bearer " + token)
|
r.Header.Add("Authorization","Bearer " + token)
|
||||||
w = httptest.NewRecorder()
|
w = httptest.NewRecorder()
|
||||||
GetAccountUsername(w, r);
|
GetAccountUsername(w, r)
|
||||||
resp = w.Result();
|
resp = w.Result()
|
||||||
if resp.StatusCode != 200 {
|
if resp.StatusCode != 200 {
|
||||||
t.Errorf("invalid token value")
|
t.Errorf("invalid token value")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
dec = json.NewDecoder(resp.Body);
|
dec = json.NewDecoder(resp.Body)
|
||||||
var available bool;
|
var available bool
|
||||||
dec.Decode(&available);
|
dec.Decode(&available)
|
||||||
if !available {
|
if !available {
|
||||||
t.Errorf("username not available")
|
t.Errorf("username not available")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// create account
|
||||||
|
auth = base64.StdEncoding.EncodeToString([]byte("user:pass"))
|
||||||
|
r = httptest.NewRequest("GET", "/account/profile", nil)
|
||||||
|
r.Header.Add("Credentials","Basic " + auth)
|
||||||
|
r.Header.Add("Authorization","Bearer " + token)
|
||||||
|
w = httptest.NewRecorder()
|
||||||
|
AddAccount(w, r)
|
||||||
|
resp = w.Result()
|
||||||
|
if resp.StatusCode != 200 {
|
||||||
|
t.Errorf("invalid token value")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
dec = json.NewDecoder(resp.Body)
|
||||||
|
var profile Profile
|
||||||
|
dec.Decode(&profile)
|
||||||
|
if profile.Guid == nil {
|
||||||
|
t.Errorf("invalid profile")
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,11 +13,6 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
func AddAccount(w http.ResponseWriter, r *http.Request) {
|
|
||||||
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
|
|
||||||
w.WriteHeader(http.StatusOK)
|
|
||||||
}
|
|
||||||
|
|
||||||
func AddAccountApp(w http.ResponseWriter, r *http.Request) {
|
func AddAccountApp(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
|
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
|
||||||
w.WriteHeader(http.StatusOK)
|
w.WriteHeader(http.StatusOK)
|
||||||
|
83
net/server/internal/auth.go
Normal file
83
net/server/internal/auth.go
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
package databag
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"strings"
|
||||||
|
"net/http"
|
||||||
|
"encoding/base64"
|
||||||
|
"golang.org/x/crypto/bcrypt"
|
||||||
|
"databag/internal/store"
|
||||||
|
)
|
||||||
|
|
||||||
|
func adminLogin(r *http.Request) bool {
|
||||||
|
|
||||||
|
// extract request auth
|
||||||
|
username, password, ok := r.BasicAuth();
|
||||||
|
if !ok || username == "" || password == "" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// nothing to do if not configured
|
||||||
|
if !getBoolConfigValue(CONFIG_CONFIGURED, false) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// compare username
|
||||||
|
if getStrConfigValue(CONFIG_USERNAME, "") != username {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// compare password
|
||||||
|
p := getBinConfigValue(CONFIG_PASSWORD, nil);
|
||||||
|
if bcrypt.CompareHashAndPassword(p, []byte(password)) != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
func bearerAccountToken(r *http.Request) (store.AccountToken, error) {
|
||||||
|
|
||||||
|
// parse bearer authentication
|
||||||
|
auth := r.Header.Get("Authorization")
|
||||||
|
token := strings.TrimSpace(strings.TrimPrefix(auth, "Bearer"))
|
||||||
|
|
||||||
|
// find token record
|
||||||
|
var accountToken store.AccountToken
|
||||||
|
err := store.DB.Where("token = ?", token).First(&accountToken).Error
|
||||||
|
return accountToken, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func basicCredentials(r *http.Request) (string, []byte, error) {
|
||||||
|
|
||||||
|
var username string
|
||||||
|
var password []byte
|
||||||
|
|
||||||
|
// parse bearer authentication
|
||||||
|
auth := r.Header.Get("Credentials")
|
||||||
|
token := strings.TrimSpace(strings.TrimPrefix(auth, "Basic"))
|
||||||
|
|
||||||
|
// decode basic auth
|
||||||
|
credentials, err := base64.StdEncoding.DecodeString(token)
|
||||||
|
if err != nil {
|
||||||
|
LogMsg("faield to decode basic credentials");
|
||||||
|
return username, password, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// parse credentials
|
||||||
|
login := strings.Split(string(credentials), ":");
|
||||||
|
if login[0] == "" || login[1] == "" {
|
||||||
|
LogMsg("failed to parse basic credentials");
|
||||||
|
return username, password, errors.New("invalid credentials")
|
||||||
|
}
|
||||||
|
username = login[0]
|
||||||
|
|
||||||
|
// hash password
|
||||||
|
password, err = bcrypt.GenerateFromPassword([]byte(login[1]), bcrypt.DefaultCost)
|
||||||
|
if err != nil {
|
||||||
|
LogMsg("failed to hash password")
|
||||||
|
return username, password, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return username, password, nil
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
package databag
|
package databag
|
||||||
|
|
||||||
const CONFIG_BODYLIMIT = 1048576
|
const CONFIG_BODYLIMIT = 1048576
|
||||||
|
const CONFIG_VERSION = "0.0.1"
|
||||||
|
|
||||||
const CONFIG_CONFIGURED = "configured"
|
const CONFIG_CONFIGURED = "configured"
|
||||||
const CONFIG_USERNAME = "username"
|
const CONFIG_USERNAME = "username"
|
||||||
|
@ -16,6 +16,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
|
"github.com/kr/pretty"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Logger(inner http.Handler, name string) http.Handler {
|
func Logger(inner http.Handler, name string) http.Handler {
|
||||||
@ -39,3 +40,7 @@ func LogMsg(msg string) {
|
|||||||
p, _ := os.Getwd()
|
p, _ := os.Getwd()
|
||||||
log.Printf("%s:%d %s", strings.TrimPrefix(file, p), line, msg)
|
log.Printf("%s:%d %s", strings.TrimPrefix(file, p), line, msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func PrintMsg(obj interface{}) {
|
||||||
|
pretty.Println(obj);
|
||||||
|
}
|
||||||
|
@ -43,11 +43,10 @@ func Claimable() {
|
|||||||
func Claim() {
|
func Claim() {
|
||||||
auth := base64.StdEncoding.EncodeToString([]byte("admin:pass"))
|
auth := base64.StdEncoding.EncodeToString([]byte("admin:pass"))
|
||||||
r := httptest.NewRequest("PUT", "/admin/claim", nil)
|
r := httptest.NewRequest("PUT", "/admin/claim", nil)
|
||||||
r.Header.Add("Authorization","Basic " + auth)
|
r.Header.Add("Credentials","Basic " + auth)
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
SetNodeClaim(w, r)
|
SetNodeClaim(w, r)
|
||||||
if w.Code != 200 {
|
if w.Code != 200 {
|
||||||
LogMsg("HERE");
|
|
||||||
panic("server not initially claimable")
|
panic("server not initially claimable")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -230,7 +230,7 @@ type NodeConfig struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Profile struct {
|
type Profile struct {
|
||||||
ProfileId string `json:"profileId"`
|
Guid string `json:"profileId"`
|
||||||
Handle string `json:"handle,omitempty"`
|
Handle string `json:"handle,omitempty"`
|
||||||
Name string `json:"name,omitempty"`
|
Name string `json:"name,omitempty"`
|
||||||
Description string `json:"description,omitempty"`
|
Description string `json:"description,omitempty"`
|
||||||
|
@ -5,7 +5,6 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
"databag/internal/store"
|
"databag/internal/store"
|
||||||
"golang.org/x/crypto/bcrypt"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func SetNodeClaim(w http.ResponseWriter, r *http.Request) {
|
func SetNodeClaim(w http.ResponseWriter, r *http.Request) {
|
||||||
@ -21,24 +20,18 @@ func SetNodeClaim(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
username, password, ok := r.BasicAuth();
|
username, password, res := basicCredentials(r);
|
||||||
if !ok || username == "" || password == "" {
|
if res != nil {
|
||||||
LogMsg("SetNodeClaim - invalid credenitals");
|
LogMsg("invalid credenitals");
|
||||||
w.WriteHeader(http.StatusBadRequest)
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
|
|
||||||
if err != nil {
|
|
||||||
LogMsg("SetNodeClaim - failed to hash password");
|
|
||||||
w.WriteHeader(http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
err = store.DB.Transaction(func(tx *gorm.DB) error {
|
err = store.DB.Transaction(func(tx *gorm.DB) error {
|
||||||
if res := tx.Create(&store.Config{ConfigId: CONFIG_USERNAME, StrValue: username}).Error; res != nil {
|
if res := tx.Create(&store.Config{ConfigId: CONFIG_USERNAME, StrValue: username}).Error; res != nil {
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
if res := tx.Create(&store.Config{ConfigId: CONFIG_PASSWORD, BinValue: hashedPassword}).Error; res != nil {
|
if res := tx.Create(&store.Config{ConfigId: CONFIG_PASSWORD, BinValue: password}).Error; res != nil {
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
if res := tx.Create(&store.Config{ConfigId: CONFIG_CONFIGURED, BoolValue: true}).Error; res != nil {
|
if res := tx.Create(&store.Config{ConfigId: CONFIG_CONFIGURED, BoolValue: true}).Error; res != nil {
|
||||||
|
@ -5,6 +5,7 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"net/http"
|
"net/http"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
|
"gorm.io/gorm/clause"
|
||||||
"databag/internal/store"
|
"databag/internal/store"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -30,15 +31,31 @@ func SetNodeConfig(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
// store credentials
|
// store credentials
|
||||||
err := store.DB.Transaction(func(tx *gorm.DB) error {
|
err := store.DB.Transaction(func(tx *gorm.DB) error {
|
||||||
if res := tx.Create(&store.Config{ConfigId: CONFIG_DOMAIN, StrValue: config.Domain}).Error; res != nil {
|
|
||||||
|
// upsert domain config
|
||||||
|
if res := tx.Clauses(clause.OnConflict{
|
||||||
|
Columns: []clause.Column{{Name: "config_id"}},
|
||||||
|
DoUpdates: clause.AssignmentColumns([]string{"str_value"}),
|
||||||
|
}).Create(&store.Config{ConfigId: CONFIG_DOMAIN, StrValue: config.Domain}).Error; res != nil {
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
if res := tx.Create(&store.Config{ConfigId: CONFIG_PUBLICLIMIT, NumValue: config.PublicLimit}).Error; res != nil {
|
|
||||||
|
// upsert public limit config
|
||||||
|
if res := tx.Clauses(clause.OnConflict{
|
||||||
|
Columns: []clause.Column{{Name: "config_id"}},
|
||||||
|
DoUpdates: clause.AssignmentColumns([]string{"num_value"}),
|
||||||
|
}).Create(&store.Config{ConfigId: CONFIG_PUBLICLIMIT, NumValue: config.PublicLimit}).Error; res != nil {
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
if res := tx.Create(&store.Config{ConfigId: CONFIG_STORAGE, NumValue: config.AccountStorage}).Error; res != nil {
|
|
||||||
|
// upsert account storage config
|
||||||
|
if res := tx.Clauses(clause.OnConflict{
|
||||||
|
Columns: []clause.Column{{Name: "config_id"}},
|
||||||
|
DoUpdates: clause.AssignmentColumns([]string{"num_value"}),
|
||||||
|
}).Create(&store.Config{ConfigId: CONFIG_STORAGE, NumValue: config.AccountStorage}).Error; res != nil {
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil;
|
return nil;
|
||||||
})
|
})
|
||||||
if(err != nil) {
|
if(err != nil) {
|
||||||
|
@ -46,24 +46,24 @@ type AccountToken struct {
|
|||||||
|
|
||||||
type Account struct {
|
type Account struct {
|
||||||
ID uint `gorm:"primaryKey;not null;unique;autoIncrement"`
|
ID uint `gorm:"primaryKey;not null;unique;autoIncrement"`
|
||||||
PublicKey []byte `gorm:"not null"`
|
PublicKey string `gorm:"not null"`
|
||||||
PrivateKey []byte `gorm:"not null"`
|
PrivateKey string `gorm:"not null"`
|
||||||
KeyType []byte `gorm:"not null"`
|
KeyType string `gorm:"not null"`
|
||||||
ProfileId string `gorm:"not null;uniqueIndex"`
|
Guid string `gorm:"not null;uniqueIndex"`
|
||||||
Username string `gorm:"not null;uniqueIndex"`
|
Username string `gorm:"not null;uniqueIndex"`
|
||||||
Password []byte `gorm:"not null"`
|
Password []byte `gorm:"not null"`
|
||||||
Name string
|
Name string
|
||||||
Description string
|
Description string
|
||||||
Location string
|
Location string
|
||||||
Image string
|
Image string
|
||||||
ProfileRevision int64 `gorm:"not null"`
|
ProfileRevision int64 `gorm:"not null;default:1"`
|
||||||
ContentRevision int64 `gorm:"not null"`
|
ContentRevision int64 `gorm:"not null;default:1"`
|
||||||
ViewRevision int64 `gorm:"not null"`
|
ViewRevision int64 `gorm:"not null;default:1"`
|
||||||
GroupRevision int64 `gorm:"not null"`
|
GroupRevision int64 `gorm:"not null;default:1"`
|
||||||
LabelRevision int64 `gorm:"not null"`
|
LabelRevision int64 `gorm:"not null;default:1"`
|
||||||
CardRevision int64 `gorm:"not null"`
|
CardRevision int64 `gorm:"not null;default:1"`
|
||||||
DialogueRevision int64 `gorm:"not null"`
|
DialogueRevision int64 `gorm:"not null;default:1"`
|
||||||
InsightRevision uint64 `gorm:"not null"`
|
InsightRevision uint64 `gorm:"not null;default:1"`
|
||||||
Created int64 `gorm:"autoCreateTime"`
|
Created int64 `gorm:"autoCreateTime"`
|
||||||
Apps []App
|
Apps []App
|
||||||
}
|
}
|
||||||
@ -108,7 +108,7 @@ type Card struct {
|
|||||||
ID uint `gorm:"primaryKey;not null;unique;autoIncrement"`
|
ID uint `gorm:"primaryKey;not null;unique;autoIncrement"`
|
||||||
CardId string `gorm:"not null;index:card,unique"`
|
CardId string `gorm:"not null;index:card,unique"`
|
||||||
AccountID uint `gorm:"not null;index:card,unique"`
|
AccountID uint `gorm:"not null;index:card,unique"`
|
||||||
DID string `gorm:"not null"`
|
GUID string `gorm:"not null"`
|
||||||
Username string
|
Username string
|
||||||
Name string
|
Name string
|
||||||
Description string
|
Description string
|
||||||
|
Loading…
Reference in New Issue
Block a user