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
|
||||
operationId: set-node-claim
|
||||
security:
|
||||
- basicAuth: []
|
||||
- basicCredentials: []
|
||||
parameters:
|
||||
- name: domain
|
||||
in: query
|
||||
@ -302,7 +302,7 @@ paths:
|
||||
operationId: add-public-account
|
||||
security:
|
||||
- bearerAuth: []
|
||||
- basicAuth: []
|
||||
- basicCredentials: []
|
||||
responses:
|
||||
'201':
|
||||
description: successful operation
|
||||
@ -431,7 +431,7 @@ paths:
|
||||
operationId: add-account
|
||||
security:
|
||||
- bearerAuth: []
|
||||
- basicAuth: []
|
||||
- basicCredentials: []
|
||||
responses:
|
||||
'201':
|
||||
description: successful operation
|
||||
@ -3964,11 +3964,11 @@ components:
|
||||
Profile:
|
||||
type: object
|
||||
required:
|
||||
- profileId
|
||||
- guid
|
||||
- revision
|
||||
- node
|
||||
properties:
|
||||
profileId:
|
||||
guid:
|
||||
type: string
|
||||
handle:
|
||||
type: string
|
||||
@ -4468,7 +4468,11 @@ components:
|
||||
basicAuth:
|
||||
type: http
|
||||
scheme: basic
|
||||
|
||||
|
||||
basicCredentials:
|
||||
type: http
|
||||
schema
|
||||
|
||||
bearerAuth:
|
||||
type: http
|
||||
scheme: bearer
|
||||
|
@ -7,7 +7,10 @@ require (
|
||||
github.com/gorilla/websocket v1.4.2 // indirect
|
||||
github.com/jinzhu/inflection v1.0.0 // 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/rogpeppe/go-internal v1.6.1 // indirect
|
||||
github.com/theckman/go-securerandom v0.1.1 // indirect
|
||||
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 // 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.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
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.3 h1:PlHq1bSCSZL9K0wUhbm2pGLoTWs2GwVhsP6emvGV/ZI=
|
||||
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/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
|
||||
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/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
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/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
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=
|
||||
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=
|
||||
|
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.Header.Add("Authorization","Basic " + auth)
|
||||
w := httptest.NewRecorder()
|
||||
AddNodeAccount(w, r);
|
||||
resp := w.Result();
|
||||
dec := json.NewDecoder(resp.Body);
|
||||
var token string;
|
||||
dec.Decode(&token);
|
||||
AddNodeAccount(w, r)
|
||||
resp := w.Result()
|
||||
dec := json.NewDecoder(resp.Body)
|
||||
var token string
|
||||
dec.Decode(&token)
|
||||
if resp.StatusCode != 200 {
|
||||
t.Errorf("failed to create account")
|
||||
return
|
||||
@ -28,36 +28,55 @@ func TestAccount(t *testing.T) {
|
||||
r = httptest.NewRequest("GET", "/account/token", nil)
|
||||
r.Header.Add("Authorization","Bearer " + token)
|
||||
w = httptest.NewRecorder()
|
||||
GetAccountToken(w, r);
|
||||
resp = w.Result();
|
||||
GetAccountToken(w, r)
|
||||
resp = w.Result()
|
||||
if resp.StatusCode != 200 {
|
||||
t.Errorf("invalid token value")
|
||||
return
|
||||
}
|
||||
dec = json.NewDecoder(resp.Body);
|
||||
var tokenType string;
|
||||
dec.Decode(&tokenType);
|
||||
dec = json.NewDecoder(resp.Body)
|
||||
var tokenType string
|
||||
dec.Decode(&tokenType)
|
||||
if tokenType != "create" {
|
||||
t.Errorf("invalid token type")
|
||||
return
|
||||
}
|
||||
|
||||
// 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)
|
||||
w = httptest.NewRecorder()
|
||||
GetAccountUsername(w, r);
|
||||
resp = w.Result();
|
||||
GetAccountUsername(w, r)
|
||||
resp = w.Result()
|
||||
if resp.StatusCode != 200 {
|
||||
t.Errorf("invalid token value")
|
||||
return
|
||||
}
|
||||
dec = json.NewDecoder(resp.Body);
|
||||
var available bool;
|
||||
dec.Decode(&available);
|
||||
dec = json.NewDecoder(resp.Body)
|
||||
var available bool
|
||||
dec.Decode(&available)
|
||||
if !available {
|
||||
t.Errorf("username not available")
|
||||
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"
|
||||
)
|
||||
|
||||
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) {
|
||||
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
|
||||
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
|
||||
|
||||
const CONFIG_BODYLIMIT = 1048576
|
||||
const CONFIG_VERSION = "0.0.1"
|
||||
|
||||
const CONFIG_CONFIGURED = "configured"
|
||||
const CONFIG_USERNAME = "username"
|
||||
|
@ -16,6 +16,7 @@ import (
|
||||
"os"
|
||||
"runtime"
|
||||
"strings"
|
||||
"github.com/kr/pretty"
|
||||
)
|
||||
|
||||
func Logger(inner http.Handler, name string) http.Handler {
|
||||
@ -39,3 +40,7 @@ func LogMsg(msg string) {
|
||||
p, _ := os.Getwd()
|
||||
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() {
|
||||
auth := base64.StdEncoding.EncodeToString([]byte("admin:pass"))
|
||||
r := httptest.NewRequest("PUT", "/admin/claim", nil)
|
||||
r.Header.Add("Authorization","Basic " + auth)
|
||||
r.Header.Add("Credentials","Basic " + auth)
|
||||
w := httptest.NewRecorder()
|
||||
SetNodeClaim(w, r)
|
||||
if w.Code != 200 {
|
||||
LogMsg("HERE");
|
||||
panic("server not initially claimable")
|
||||
}
|
||||
}
|
||||
|
@ -230,7 +230,7 @@ type NodeConfig struct {
|
||||
}
|
||||
|
||||
type Profile struct {
|
||||
ProfileId string `json:"profileId"`
|
||||
Guid string `json:"profileId"`
|
||||
Handle string `json:"handle,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
Description string `json:"description,omitempty"`
|
||||
|
@ -5,7 +5,6 @@ import (
|
||||
"net/http"
|
||||
"gorm.io/gorm"
|
||||
"databag/internal/store"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
)
|
||||
|
||||
func SetNodeClaim(w http.ResponseWriter, r *http.Request) {
|
||||
@ -21,24 +20,18 @@ func SetNodeClaim(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
username, password, ok := r.BasicAuth();
|
||||
if !ok || username == "" || password == "" {
|
||||
LogMsg("SetNodeClaim - invalid credenitals");
|
||||
username, password, res := basicCredentials(r);
|
||||
if res != nil {
|
||||
LogMsg("invalid credenitals");
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
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 {
|
||||
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 {
|
||||
if res := tx.Create(&store.Config{ConfigId: CONFIG_PASSWORD, BinValue: password}).Error; res != nil {
|
||||
return res
|
||||
}
|
||||
if res := tx.Create(&store.Config{ConfigId: CONFIG_CONFIGURED, BoolValue: true}).Error; res != nil {
|
||||
|
@ -5,6 +5,7 @@ import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/gorm/clause"
|
||||
"databag/internal/store"
|
||||
)
|
||||
|
||||
@ -30,15 +31,31 @@ func SetNodeConfig(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
// 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 {
|
||||
|
||||
// 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
|
||||
}
|
||||
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
|
||||
}
|
||||
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 nil;
|
||||
})
|
||||
if(err != nil) {
|
||||
|
@ -46,24 +46,24 @@ type AccountToken struct {
|
||||
|
||||
type Account struct {
|
||||
ID uint `gorm:"primaryKey;not null;unique;autoIncrement"`
|
||||
PublicKey []byte `gorm:"not null"`
|
||||
PrivateKey []byte `gorm:"not null"`
|
||||
KeyType []byte `gorm:"not null"`
|
||||
ProfileId string `gorm:"not null;uniqueIndex"`
|
||||
PublicKey string `gorm:"not null"`
|
||||
PrivateKey string `gorm:"not null"`
|
||||
KeyType string `gorm:"not null"`
|
||||
Guid string `gorm:"not null;uniqueIndex"`
|
||||
Username string `gorm:"not null;uniqueIndex"`
|
||||
Password []byte `gorm:"not null"`
|
||||
Name string
|
||||
Description string
|
||||
Location string
|
||||
Image string
|
||||
ProfileRevision int64 `gorm:"not null"`
|
||||
ContentRevision int64 `gorm:"not null"`
|
||||
ViewRevision int64 `gorm:"not null"`
|
||||
GroupRevision int64 `gorm:"not null"`
|
||||
LabelRevision int64 `gorm:"not null"`
|
||||
CardRevision int64 `gorm:"not null"`
|
||||
DialogueRevision int64 `gorm:"not null"`
|
||||
InsightRevision uint64 `gorm:"not null"`
|
||||
ProfileRevision int64 `gorm:"not null;default:1"`
|
||||
ContentRevision int64 `gorm:"not null;default:1"`
|
||||
ViewRevision int64 `gorm:"not null;default:1"`
|
||||
GroupRevision int64 `gorm:"not null;default:1"`
|
||||
LabelRevision int64 `gorm:"not null;default:1"`
|
||||
CardRevision int64 `gorm:"not null;default:1"`
|
||||
DialogueRevision int64 `gorm:"not null;default:1"`
|
||||
InsightRevision uint64 `gorm:"not null;default:1"`
|
||||
Created int64 `gorm:"autoCreateTime"`
|
||||
Apps []App
|
||||
}
|
||||
@ -108,7 +108,7 @@ type Card struct {
|
||||
ID uint `gorm:"primaryKey;not null;unique;autoIncrement"`
|
||||
CardId string `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
|
||||
Name string
|
||||
Description string
|
||||
|
Loading…
Reference in New Issue
Block a user