This repository has been archived by the owner on Apr 2, 2024. It is now read-only.
generated from mrz1836/go-template
-
-
Notifications
You must be signed in to change notification settings - Fork 7
/
model_access_keys.go
197 lines (167 loc) · 5.93 KB
/
model_access_keys.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
package bux
import (
"context"
"database/sql"
"encoding/hex"
"errors"
"github.com/BuxOrg/bux/utils"
"github.com/bitcoinschema/go-bitcoin/v2"
"github.com/mrz1836/go-datastore"
customTypes "github.com/mrz1836/go-datastore/custom_types"
)
// AccessKey is an object representing an access key model
//
// An AccessKey is a private key with a corresponding public key
// The public key is hashed and saved in this model for retrieval.
// When a request is made with an access key, the public key is sent in the headers, together with
// a signature (like normally done with xPriv signing)
//
// Gorm related models & indexes: https://gorm.io/docs/models.html - https://gorm.io/docs/indexes.html
type AccessKey struct {
// Base model
Model `bson:",inline"`
// Model specific fields
ID string `json:"id" toml:"id" yaml:"id" gorm:"<-:create;type:char(64);primaryKey;comment:This is the unique access key id" bson:"_id"`
XpubID string `json:"xpub_id" toml:"xpub_id" yaml:"hash" gorm:"<-:create;type:char(64);index;comment:This is the related xPub id" bson:"xpub_id"`
RevokedAt customTypes.NullTime `json:"revoked_at" toml:"revoked_at" yaml:"revoked_at" gorm:"<-;comment:When the key was revoked" bson:"revoked_at,omitempty"`
// Private fields
Key string `json:"key" gorm:"-" bson:"-"` // Used on "CREATE", shown to the user "once" only
}
// newAccessKey will start a new model
func newAccessKey(xPubID string, opts ...ModelOps) *AccessKey {
privateKey, _ := bitcoin.CreatePrivateKey()
publicKey := hex.EncodeToString(privateKey.PubKey().SerialiseCompressed())
id := utils.Hash(publicKey)
return &AccessKey{
ID: id,
Model: *NewBaseModel(ModelAccessKey, opts...),
XpubID: xPubID,
RevokedAt: customTypes.NullTime{NullTime: sql.NullTime{
Valid: false,
}},
Key: hex.EncodeToString(privateKey.Serialise()),
}
}
// getAccessKey will get the model with a given ID
func getAccessKey(ctx context.Context, id string, opts ...ModelOps) (*AccessKey, error) {
// Construct an empty tx
key := &AccessKey{
ID: id,
}
key.enrich(ModelAccessKey, opts...)
// Get the record
if err := Get(ctx, key, nil, false, defaultDatabaseReadTimeout, false); err != nil {
if errors.Is(err, datastore.ErrNoResults) {
return nil, nil
}
return nil, err
}
return key, nil
}
// getAccessKeys will get all the access keys with the given conditions
func getAccessKeys(ctx context.Context, metadata *Metadata, conditions *map[string]interface{},
queryParams *datastore.QueryParams, opts ...ModelOps,
) ([]*AccessKey, error) {
modelItems := make([]*AccessKey, 0)
if err := getModelsByConditions(ctx, ModelAccessKey, &modelItems, metadata, conditions, queryParams, opts...); err != nil {
return nil, err
}
return modelItems, nil
}
// getAccessKeysCount will get a count of all the access keys with the given conditions
func getAccessKeysCount(ctx context.Context, metadata *Metadata, conditions *map[string]interface{},
opts ...ModelOps,
) (int64, error) {
return getModelCountByConditions(ctx, ModelAccessKey, AccessKey{}, metadata, conditions, opts...)
}
// getAccessKeysByXPubID will get all the access keys that match the metadata search
func getAccessKeysByXPubID(ctx context.Context, xPubID string, metadata *Metadata, conditions *map[string]interface{},
queryParams *datastore.QueryParams, opts ...ModelOps,
) ([]*AccessKey, error) {
// Construct an empty model
var models []AccessKey
dbConditions := map[string]interface{}{}
if conditions != nil {
dbConditions = *conditions
}
dbConditions[xPubIDField] = xPubID
if metadata != nil {
dbConditions[metadataField] = metadata
}
// Get the records
if err := getModels(
ctx, NewBaseModel(ModelNameEmpty, opts...).Client().Datastore(),
&models, dbConditions, queryParams, defaultDatabaseReadTimeout,
); err != nil {
if errors.Is(err, datastore.ErrNoResults) {
return nil, nil
}
return nil, err
}
// Loop and enrich
accessKeys := make([]*AccessKey, 0)
for index := range models {
models[index].enrich(ModelDestination, opts...)
accessKeys = append(accessKeys, &models[index])
}
return accessKeys, nil
}
// getAccessKeysByXPubIDCount will get a count of all the access keys that match the metadata search
func getAccessKeysByXPubIDCount(ctx context.Context, xPubID string, metadata *Metadata,
conditions *map[string]interface{}, opts ...ModelOps,
) (int64, error) {
dbConditions := map[string]interface{}{}
if conditions != nil {
dbConditions = *conditions
}
dbConditions[xPubIDField] = xPubID
if metadata != nil {
dbConditions[metadataField] = metadata
}
// Get the records
count, err := getModelCount(
ctx, NewBaseModel(ModelNameEmpty, opts...).Client().Datastore(),
AccessKey{}, dbConditions, defaultDatabaseReadTimeout,
)
if err != nil {
if errors.Is(err, datastore.ErrNoResults) {
return 0, nil
}
return 0, err
}
return count, nil
}
// GetModelName will get the name of the current model
func (m *AccessKey) GetModelName() string {
return ModelAccessKey.String()
}
// GetModelTableName will get the db table name of the current model
func (m *AccessKey) GetModelTableName() string {
return tableAccessKeys
}
// Save will save the model into the Datastore
func (m *AccessKey) Save(ctx context.Context) error {
return Save(ctx, m)
}
// GetID will get the ID
func (m *AccessKey) GetID() string {
return m.ID
}
// BeforeCreating will fire before the model is being inserted into the Datastore
func (m *AccessKey) BeforeCreating(_ context.Context) error {
m.Client().Logger().Debug().
Str("accessKeyID", m.ID).
Msgf("starting: %s BeforeCreating hook...", m.Name())
// Make sure ID is valid
if len(m.ID) == 0 {
return ErrMissingFieldID
}
m.Client().Logger().Debug().
Str("accessKeyID", m.ID).
Msgf("end: %s BeforeCreating hook", m.Name())
return nil
}
// Migrate model specific migration on startup
func (m *AccessKey) Migrate(client datastore.ClientInterface) error {
return client.IndexMetadata(client.GetTableName(tableAccessKeys), metadataField)
}