Refactor
This commit is contained in:
parent
c5f978d32b
commit
02ff452c09
10 changed files with 89 additions and 77 deletions
|
@ -1,4 +1,4 @@
|
||||||
package pkg
|
package internal
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"cli-go/internal/api"
|
"cli-go/internal/api"
|
5
main.go
5
main.go
|
@ -4,6 +4,7 @@ import (
|
||||||
"cli-go/cmd"
|
"cli-go/cmd"
|
||||||
"cli-go/internal/api"
|
"cli-go/internal/api"
|
||||||
"cli-go/pkg"
|
"cli-go/pkg"
|
||||||
|
"cli-go/pkg/secrets"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
@ -17,8 +18,8 @@ func main() {
|
||||||
Host: "http://localhost:8080",
|
Host: "http://localhost:8080",
|
||||||
}),
|
}),
|
||||||
DB: db,
|
DB: db,
|
||||||
CliKey: pkg.GetOrCreateClISecret(),
|
CliKey: secrets.GetOrCreateClISecret(),
|
||||||
KeyHolder: pkg.NewKeyHolder(),
|
KeyHolder: secrets.NewKeyHolder(),
|
||||||
}
|
}
|
||||||
err = ctrl.Init()
|
err = ctrl.Init()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package pkg
|
package pkg
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"cli-go/internal"
|
||||||
"cli-go/internal/api"
|
"cli-go/internal/api"
|
||||||
"cli-go/pkg/model"
|
"cli-go/pkg/model"
|
||||||
"cli-go/utils/encoding"
|
"cli-go/utils/encoding"
|
||||||
|
@ -21,9 +22,9 @@ func (c *ClICtrl) AddAccount(cxt context.Context) {
|
||||||
log.Fatal(flowErr)
|
log.Fatal(flowErr)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
app := GetAppType()
|
app := internal.GetAppType()
|
||||||
cxt = context.WithValue(cxt, "app", string(app))
|
cxt = context.WithValue(cxt, "app", string(app))
|
||||||
email, flowErr := GetUserInput("Enter email address")
|
email, flowErr := internal.GetUserInput("Enter email address")
|
||||||
if flowErr != nil {
|
if flowErr != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -69,7 +70,7 @@ func (c *ClICtrl) AddAccount(cxt context.Context) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ClICtrl) storeAccount(_ context.Context, email string, userID int64, app api.App, secretInfo *accSecretInfo) error {
|
func (c *ClICtrl) storeAccount(_ context.Context, email string, userID int64, app api.App, secretInfo *model.AccSecretInfo) error {
|
||||||
// get password
|
// get password
|
||||||
secret := c.CliKey
|
secret := c.CliKey
|
||||||
err := c.DB.Update(func(tx *bolt.Tx) error {
|
err := c.DB.Update(func(tx *bolt.Tx) error {
|
||||||
|
|
57
pkg/collections.go
Normal file
57
pkg/collections.go
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
package pkg
|
||||||
|
|
||||||
|
import (
|
||||||
|
"cli-go/internal/api"
|
||||||
|
enteCrypto "cli-go/internal/crypto"
|
||||||
|
"cli-go/pkg/model"
|
||||||
|
"cli-go/utils/encoding"
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (c *ClICtrl) syncRemoteCollections(ctx context.Context, info model.Account) error {
|
||||||
|
collections, err := c.Client.GetCollections(ctx, 0)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to get collections: %s", err)
|
||||||
|
}
|
||||||
|
for _, collection := range collections {
|
||||||
|
collectionKey, err := c.getCollectionKey(ctx, collection)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
name, nameErr := enteCrypto.SecretBoxOpenBase64(collection.EncryptedName, collection.NameDecryptionNonce, collectionKey)
|
||||||
|
if nameErr != nil {
|
||||||
|
log.Fatalf("failed to decrypt collection name: %v", nameErr)
|
||||||
|
}
|
||||||
|
if collection.Owner.ID != info.UserID {
|
||||||
|
fmt.Printf("Shared Album %s\n", string(name))
|
||||||
|
continue
|
||||||
|
} else {
|
||||||
|
fmt.Printf("Owned Name %s\n", string(name))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ClICtrl) getCollectionKey(ctx context.Context, collection api.Collection) ([]byte, error) {
|
||||||
|
accSecretInfo := c.KeyHolder.GetAccountSecretInfo(ctx)
|
||||||
|
userID := ctx.Value("user_id").(int64)
|
||||||
|
if collection.Owner.ID == userID {
|
||||||
|
collKey, err := enteCrypto.SecretBoxOpen(
|
||||||
|
encoding.DecodeBase64(collection.EncryptedKey),
|
||||||
|
encoding.DecodeBase64(collection.KeyDecryptionNonce),
|
||||||
|
accSecretInfo.MasterKey)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("failed to decrypt collection key %s", err)
|
||||||
|
}
|
||||||
|
return collKey, nil
|
||||||
|
} else {
|
||||||
|
collKey, err := enteCrypto.SealedBoxOpen(encoding.DecodeBase64(collection.EncryptedKey),
|
||||||
|
accSecretInfo.PublicKey, accSecretInfo.SecretKey)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("failed to decrypt collection key %s", err)
|
||||||
|
}
|
||||||
|
return collKey, nil
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,6 +2,7 @@ package pkg
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"cli-go/internal/api"
|
"cli-go/internal/api"
|
||||||
|
"cli-go/pkg/secrets"
|
||||||
"fmt"
|
"fmt"
|
||||||
bolt "go.etcd.io/bbolt"
|
bolt "go.etcd.io/bbolt"
|
||||||
)
|
)
|
||||||
|
@ -11,7 +12,7 @@ type ClICtrl struct {
|
||||||
DB *bolt.DB
|
DB *bolt.DB
|
||||||
// CliKey is the key used to encrypt/decrypt sensitive data stored in the database
|
// CliKey is the key used to encrypt/decrypt sensitive data stored in the database
|
||||||
CliKey []byte
|
CliKey []byte
|
||||||
KeyHolder *KeyHolder
|
KeyHolder *secrets.KeyHolder
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ClICtrl) Init() error {
|
func (c *ClICtrl) Init() error {
|
||||||
|
|
|
@ -23,3 +23,10 @@ func (a *Account) AccountKey() string {
|
||||||
func (a *Account) DataBucket() string {
|
func (a *Account) DataBucket() string {
|
||||||
return fmt.Sprintf("%s-%d-data", a.App, a.UserID)
|
return fmt.Sprintf("%s-%d-data", a.App, a.UserID)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type AccSecretInfo struct {
|
||||||
|
MasterKey []byte
|
||||||
|
SecretKey []byte
|
||||||
|
Token []byte
|
||||||
|
PublicKey []byte
|
||||||
|
}
|
||||||
|
|
|
@ -1,10 +1,7 @@
|
||||||
package pkg
|
package pkg
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"cli-go/internal/api"
|
|
||||||
enteCrypto "cli-go/internal/crypto"
|
|
||||||
"cli-go/pkg/model"
|
"cli-go/pkg/model"
|
||||||
"cli-go/utils/encoding"
|
|
||||||
"context"
|
"context"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
@ -51,50 +48,3 @@ func createDataBuckets(db *bolt.DB, account model.Account) error {
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ClICtrl) syncRemoteCollections(ctx context.Context, info model.Account) error {
|
|
||||||
collections, err := c.Client.GetCollections(ctx, 0)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to get collections: %s", err)
|
|
||||||
}
|
|
||||||
for _, collection := range collections {
|
|
||||||
|
|
||||||
collectionKey, err := c.getCollectionKey(ctx, collection)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
name, nameErr := enteCrypto.SecretBoxOpenBase64(collection.EncryptedName, collection.NameDecryptionNonce, collectionKey)
|
|
||||||
if nameErr != nil {
|
|
||||||
log.Fatalf("failed to decrypt collection name: %v", nameErr)
|
|
||||||
}
|
|
||||||
if collection.Owner.ID != info.UserID {
|
|
||||||
fmt.Printf("Shared Album %s\n", string(name))
|
|
||||||
continue
|
|
||||||
} else {
|
|
||||||
fmt.Printf("Owned Name %s\n", string(name))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *ClICtrl) getCollectionKey(ctx context.Context, collection api.Collection) ([]byte, error) {
|
|
||||||
accSecretInfo := c.KeyHolder.GetAccountSecretInfo(ctx)
|
|
||||||
userID := ctx.Value("user_id").(int64)
|
|
||||||
if collection.Owner.ID == userID {
|
|
||||||
collKey, err := enteCrypto.SecretBoxOpen(
|
|
||||||
encoding.DecodeBase64(collection.EncryptedKey),
|
|
||||||
encoding.DecodeBase64(collection.KeyDecryptionNonce),
|
|
||||||
accSecretInfo.MasterKey)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("failed to decrypt collection key %s", err)
|
|
||||||
}
|
|
||||||
return collKey, nil
|
|
||||||
} else {
|
|
||||||
collKey, err := enteCrypto.SealedBoxOpen(encoding.DecodeBase64(collection.EncryptedKey),
|
|
||||||
accSecretInfo.PublicKey, accSecretInfo.SecretKey)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("failed to decrypt collection key %s", err)
|
|
||||||
}
|
|
||||||
return collKey, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package pkg
|
package secrets
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"cli-go/pkg/model"
|
"cli-go/pkg/model"
|
||||||
|
@ -7,22 +7,22 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type KeyHolder struct {
|
type KeyHolder struct {
|
||||||
AccountSecrets map[string]*accSecretInfo
|
AccountSecrets map[string]*model.AccSecretInfo
|
||||||
CollectionKeys map[string][]byte
|
CollectionKeys map[string][]byte
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewKeyHolder() *KeyHolder {
|
func NewKeyHolder() *KeyHolder {
|
||||||
return &KeyHolder{
|
return &KeyHolder{
|
||||||
AccountSecrets: make(map[string]*accSecretInfo),
|
AccountSecrets: make(map[string]*model.AccSecretInfo),
|
||||||
CollectionKeys: make(map[string][]byte),
|
CollectionKeys: make(map[string][]byte),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (k *KeyHolder) LoadSecrets(account model.Account, cliKey []byte) (*accSecretInfo, error) {
|
func (k *KeyHolder) LoadSecrets(account model.Account, cliKey []byte) (*model.AccSecretInfo, error) {
|
||||||
tokenKey := account.Token.MustDecrypt(cliKey)
|
tokenKey := account.Token.MustDecrypt(cliKey)
|
||||||
masterKey := account.MasterKey.MustDecrypt(cliKey)
|
masterKey := account.MasterKey.MustDecrypt(cliKey)
|
||||||
secretKey := account.SecretKey.MustDecrypt(cliKey)
|
secretKey := account.SecretKey.MustDecrypt(cliKey)
|
||||||
k.AccountSecrets[account.AccountKey()] = &accSecretInfo{
|
k.AccountSecrets[account.AccountKey()] = &model.AccSecretInfo{
|
||||||
Token: tokenKey,
|
Token: tokenKey,
|
||||||
MasterKey: masterKey,
|
MasterKey: masterKey,
|
||||||
SecretKey: secretKey,
|
SecretKey: secretKey,
|
||||||
|
@ -31,7 +31,7 @@ func (k *KeyHolder) LoadSecrets(account model.Account, cliKey []byte) (*accSecre
|
||||||
return k.AccountSecrets[account.AccountKey()], nil
|
return k.AccountSecrets[account.AccountKey()], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (k *KeyHolder) GetAccountSecretInfo(ctx context.Context) *accSecretInfo {
|
func (k *KeyHolder) GetAccountSecretInfo(ctx context.Context) *model.AccSecretInfo {
|
||||||
accountKey := ctx.Value("account_id").(string)
|
accountKey := ctx.Value("account_id").(string)
|
||||||
return k.AccountSecrets[accountKey]
|
return k.AccountSecrets[accountKey]
|
||||||
}
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package pkg
|
package secrets
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/rand"
|
"crypto/rand"
|
|
@ -1,8 +1,10 @@
|
||||||
package pkg
|
package pkg
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"cli-go/internal"
|
||||||
"cli-go/internal/api"
|
"cli-go/internal/api"
|
||||||
enteCrypto "cli-go/internal/crypto"
|
enteCrypto "cli-go/internal/crypto"
|
||||||
|
"cli-go/pkg/model"
|
||||||
"cli-go/utils/encoding"
|
"cli-go/utils/encoding"
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
@ -11,17 +13,10 @@ import (
|
||||||
"github.com/kong/go-srp"
|
"github.com/kong/go-srp"
|
||||||
)
|
)
|
||||||
|
|
||||||
type accSecretInfo struct {
|
|
||||||
MasterKey []byte
|
|
||||||
SecretKey []byte
|
|
||||||
Token []byte
|
|
||||||
PublicKey []byte
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *ClICtrl) signInViaPassword(ctx context.Context, email string, srpAttr *api.SRPAttributes) (*api.AuthorizationResponse, []byte, error) {
|
func (c *ClICtrl) signInViaPassword(ctx context.Context, email string, srpAttr *api.SRPAttributes) (*api.AuthorizationResponse, []byte, error) {
|
||||||
for {
|
for {
|
||||||
// CLI prompt for password
|
// CLI prompt for password
|
||||||
password, flowErr := GetSensitiveField("Enter password")
|
password, flowErr := internal.GetSensitiveField("Enter password")
|
||||||
if flowErr != nil {
|
if flowErr != nil {
|
||||||
return nil, nil, flowErr
|
return nil, nil, flowErr
|
||||||
}
|
}
|
||||||
|
@ -62,7 +57,7 @@ func (c *ClICtrl) decryptAccSecretInfo(
|
||||||
_ context.Context,
|
_ context.Context,
|
||||||
authResp *api.AuthorizationResponse,
|
authResp *api.AuthorizationResponse,
|
||||||
keyEncKey []byte,
|
keyEncKey []byte,
|
||||||
) (*accSecretInfo, error) {
|
) (*model.AccSecretInfo, error) {
|
||||||
var currentKeyEncKey []byte
|
var currentKeyEncKey []byte
|
||||||
var err error
|
var err error
|
||||||
var masterKey, secretKey, tokenKey []byte
|
var masterKey, secretKey, tokenKey []byte
|
||||||
|
@ -70,7 +65,7 @@ func (c *ClICtrl) decryptAccSecretInfo(
|
||||||
for {
|
for {
|
||||||
if keyEncKey == nil {
|
if keyEncKey == nil {
|
||||||
// CLI prompt for password
|
// CLI prompt for password
|
||||||
password, flowErr := GetSensitiveField("Enter password")
|
password, flowErr := internal.GetSensitiveField("Enter password")
|
||||||
if flowErr != nil {
|
if flowErr != nil {
|
||||||
return nil, flowErr
|
return nil, flowErr
|
||||||
}
|
}
|
||||||
|
@ -117,7 +112,7 @@ func (c *ClICtrl) decryptAccSecretInfo(
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
return &accSecretInfo{
|
return &model.AccSecretInfo{
|
||||||
MasterKey: masterKey,
|
MasterKey: masterKey,
|
||||||
SecretKey: secretKey,
|
SecretKey: secretKey,
|
||||||
Token: tokenKey,
|
Token: tokenKey,
|
||||||
|
@ -131,7 +126,7 @@ func (c *ClICtrl) validateTOTP(ctx context.Context, authResp *api.AuthorizationR
|
||||||
}
|
}
|
||||||
for {
|
for {
|
||||||
// CLI prompt for TOTP
|
// CLI prompt for TOTP
|
||||||
totp, flowErr := GetCode("Enter TOTP", 6)
|
totp, flowErr := internal.GetCode("Enter TOTP", 6)
|
||||||
if flowErr != nil {
|
if flowErr != nil {
|
||||||
return nil, flowErr
|
return nil, flowErr
|
||||||
}
|
}
|
||||||
|
@ -151,7 +146,7 @@ func (c *ClICtrl) validateEmail(ctx context.Context, email string) (*api.Authori
|
||||||
}
|
}
|
||||||
for {
|
for {
|
||||||
// CLI prompt for OTP
|
// CLI prompt for OTP
|
||||||
ott, flowErr := GetCode("Enter OTP", 6)
|
ott, flowErr := internal.GetCode("Enter OTP", 6)
|
||||||
if flowErr != nil {
|
if flowErr != nil {
|
||||||
return nil, flowErr
|
return nil, flowErr
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue