mirror of
https://github.com/mitchell/selfpass.git
synced 2025-12-14 13:27:21 +00:00
Move service related filed to services folder
This commit is contained in:
parent
347fbe7268
commit
7d770ef150
41 changed files with 50 additions and 50 deletions
100
services/credentials/commands/commands.go
Normal file
100
services/credentials/commands/commands.go
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
package commands
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"sort"
|
||||
"time"
|
||||
|
||||
"gopkg.in/AlecAivazis/survey.v1"
|
||||
|
||||
"github.com/mitchell/selfpass/services/credentials/types"
|
||||
)
|
||||
|
||||
type CredentialClientInit func(ctx context.Context) (c types.CredentialClient)
|
||||
|
||||
func check(err error) {
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func selectCredential(client types.CredentialClient) types.Credential {
|
||||
var (
|
||||
idKey string
|
||||
source string
|
||||
prompt survey.Prompt
|
||||
)
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
||||
defer cancel()
|
||||
|
||||
mdch, errch := client.GetAllMetadata(ctx, "")
|
||||
mds := map[string][]types.Metadata{}
|
||||
|
||||
fmt.Println()
|
||||
|
||||
receive:
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
check(ctx.Err())
|
||||
|
||||
case err := <-errch:
|
||||
check(err)
|
||||
|
||||
case md, ok := <-mdch:
|
||||
if !ok {
|
||||
break receive
|
||||
}
|
||||
|
||||
mds[md.SourceHost] = append(mds[md.SourceHost], md)
|
||||
}
|
||||
}
|
||||
|
||||
sources := []string{}
|
||||
for source := range mds {
|
||||
sources = append(sources, source)
|
||||
}
|
||||
|
||||
sort.Strings(sources)
|
||||
|
||||
prompt = &survey.Select{
|
||||
Message: "Source host:",
|
||||
Options: sources,
|
||||
PageSize: 20,
|
||||
VimMode: true,
|
||||
}
|
||||
|
||||
check(survey.AskOne(prompt, &source, nil))
|
||||
|
||||
keys := []string{}
|
||||
keyIDMap := map[string]string{}
|
||||
for _, md := range mds[source] {
|
||||
key := md.Primary
|
||||
if md.Tag != "" {
|
||||
key += "-" + md.Tag
|
||||
}
|
||||
keys = append(keys, key)
|
||||
keyIDMap[key] = md.ID
|
||||
}
|
||||
|
||||
prompt = &survey.Select{
|
||||
Message: "Primary user key (and tag):",
|
||||
Options: keys,
|
||||
PageSize: 20,
|
||||
VimMode: true,
|
||||
}
|
||||
|
||||
check(survey.AskOne(prompt, &idKey, nil))
|
||||
|
||||
ctx, cancel = context.WithTimeout(context.Background(), time.Second*5)
|
||||
defer cancel()
|
||||
|
||||
cred, err := client.Get(ctx, keyIDMap[idKey])
|
||||
check(err)
|
||||
|
||||
return cred
|
||||
}
|
||||
155
services/credentials/commands/create.go
Normal file
155
services/credentials/commands/create.go
Normal file
|
|
@ -0,0 +1,155 @@
|
|||
package commands
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/atotto/clipboard"
|
||||
"github.com/pquerna/otp/totp"
|
||||
"github.com/spf13/cobra"
|
||||
"gopkg.in/AlecAivazis/survey.v1"
|
||||
|
||||
clitypes "github.com/mitchell/selfpass/services/cli/types"
|
||||
"github.com/mitchell/selfpass/services/credentials/types"
|
||||
"github.com/mitchell/selfpass/services/crypto"
|
||||
)
|
||||
|
||||
func MakeCreate(repo clitypes.ConfigRepo, initClient CredentialClientInit) *cobra.Command {
|
||||
var length uint
|
||||
var numbers bool
|
||||
var specials bool
|
||||
|
||||
createCmd := &cobra.Command{
|
||||
Use: "create",
|
||||
Short: "Create a credential in Selfpass",
|
||||
Long: `Create a credential in Selfpass, and save it to the server after encrypting the
|
||||
password.`,
|
||||
|
||||
Run: func(_ *cobra.Command, args []string) {
|
||||
var (
|
||||
otp bool
|
||||
cleancb bool
|
||||
newpass bool
|
||||
ci types.CredentialInput
|
||||
)
|
||||
|
||||
masterpass, cfg, err := repo.OpenConfig()
|
||||
check(err)
|
||||
|
||||
mdqs := []*survey.Question{
|
||||
{
|
||||
Name: "primary",
|
||||
Prompt: &survey.Input{Message: "Primary user key:"},
|
||||
},
|
||||
{
|
||||
Name: "sourceHost",
|
||||
Prompt: &survey.Input{Message: "Source host:"},
|
||||
},
|
||||
{
|
||||
Name: "loginURL",
|
||||
Prompt: &survey.Input{Message: "Login url:"},
|
||||
},
|
||||
{
|
||||
Name: "tag",
|
||||
Prompt: &survey.Input{Message: "Tag:"},
|
||||
},
|
||||
}
|
||||
cqs := []*survey.Question{
|
||||
{
|
||||
Name: "username",
|
||||
Prompt: &survey.Input{Message: "Username:"},
|
||||
},
|
||||
{
|
||||
Name: "email",
|
||||
Prompt: &survey.Input{Message: "Email:"},
|
||||
},
|
||||
}
|
||||
check(survey.Ask(mdqs, &ci.MetadataInput))
|
||||
check(survey.Ask(cqs, &ci))
|
||||
|
||||
key := cfg.GetString(clitypes.KeyPrivateKey)
|
||||
keypass := crypto.GeneratePBKDF2Key([]byte(masterpass), []byte(key))
|
||||
|
||||
prompt := &survey.Confirm{Message: "Do you want a random password?", Default: true}
|
||||
check(survey.AskOne(prompt, &newpass, nil))
|
||||
|
||||
if newpass {
|
||||
ci.Password = crypto.GeneratePassword(int(length), numbers, specials)
|
||||
|
||||
var copypass bool
|
||||
prompt = &survey.Confirm{Message: "Copy new pass to clipboard?", Default: true}
|
||||
check(survey.AskOne(prompt, ©pass, nil))
|
||||
|
||||
if copypass {
|
||||
check(clipboard.WriteAll(ci.Password))
|
||||
}
|
||||
} else {
|
||||
prompt := &survey.Password{Message: "Password: "}
|
||||
check(survey.AskOne(prompt, &ci.Password, nil))
|
||||
|
||||
var cpass string
|
||||
prompt = &survey.Password{Message: "Confirm password: "}
|
||||
check(survey.AskOne(prompt, &cpass, nil))
|
||||
|
||||
if ci.Password != cpass {
|
||||
fmt.Println("passwords didn't match")
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
cipherpass, err := crypto.CBCEncrypt(keypass, []byte(ci.Password))
|
||||
check(err)
|
||||
|
||||
ci.Password = base64.StdEncoding.EncodeToString(cipherpass)
|
||||
|
||||
prompt = &survey.Confirm{Message: "Do you have an OTP/MFA secret?", Default: true}
|
||||
check(survey.AskOne(prompt, &otp, nil))
|
||||
|
||||
if otp {
|
||||
var secret string
|
||||
prompt := &survey.Password{Message: "OTP secret:"}
|
||||
check(survey.AskOne(prompt, &secret, nil))
|
||||
|
||||
ciphersecret, err := crypto.CBCEncrypt(keypass, []byte(secret))
|
||||
check(err)
|
||||
|
||||
ci.OTPSecret = base64.StdEncoding.EncodeToString(ciphersecret)
|
||||
|
||||
var copyotp bool
|
||||
prompt2 := &survey.Confirm{Message: "Copy new OTP to clipboard?", Default: true}
|
||||
check(survey.AskOne(prompt2, ©otp, nil))
|
||||
|
||||
if copyotp {
|
||||
otp, err := totp.GenerateCode(secret, time.Now())
|
||||
check(err)
|
||||
|
||||
check(clipboard.WriteAll(otp))
|
||||
}
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*25)
|
||||
defer cancel()
|
||||
|
||||
c, err := initClient(ctx).Create(ctx, ci)
|
||||
check(err)
|
||||
|
||||
fmt.Println(c)
|
||||
|
||||
prompt = &survey.Confirm{Message: "Do you want to clear the clipboard?", Default: true}
|
||||
check(survey.AskOne(prompt, &cleancb, nil))
|
||||
|
||||
if cleancb {
|
||||
check(clipboard.WriteAll(" "))
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
createCmd.Flags().BoolVarP(&numbers, "numbers", "n", true, "use numbers in the generated password")
|
||||
createCmd.Flags().BoolVarP(&specials, "specials", "s", false, "use special characters in the generated password")
|
||||
createCmd.Flags().UintVarP(&length, "length", "l", 32, "length of the generated password")
|
||||
|
||||
return createCmd
|
||||
}
|
||||
42
services/credentials/commands/delete.go
Normal file
42
services/credentials/commands/delete.go
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
package commands
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"gopkg.in/AlecAivazis/survey.v1"
|
||||
)
|
||||
|
||||
func MakeDelete(initClient CredentialClientInit) *cobra.Command {
|
||||
deleteCmd := &cobra.Command{
|
||||
Use: "delete",
|
||||
Short: "Delete a credential using the given ID",
|
||||
Long: `Delete a credential using the given ID, permanently. THERE IS NO UNDOING THIS ACTION.`,
|
||||
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*15)
|
||||
defer cancel()
|
||||
|
||||
client := initClient(ctx)
|
||||
|
||||
cred := selectCredential(client)
|
||||
|
||||
fmt.Println(cred)
|
||||
|
||||
var confirmed bool
|
||||
prompt := &survey.Confirm{Message: "Are you sure you want to permanently delete this credential?"}
|
||||
check(survey.AskOne(prompt, &confirmed, nil))
|
||||
|
||||
if confirmed {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*25)
|
||||
defer cancel()
|
||||
|
||||
check(initClient(ctx).Delete(ctx, cred.ID))
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
return deleteCmd
|
||||
}
|
||||
108
services/credentials/commands/gcm-to-cbc.go
Normal file
108
services/credentials/commands/gcm-to-cbc.go
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
package commands
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
clitypes "github.com/mitchell/selfpass/services/cli/types"
|
||||
"github.com/mitchell/selfpass/services/credentials/types"
|
||||
"github.com/mitchell/selfpass/services/crypto"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func MakeGCMToCBC(repo clitypes.ConfigRepo, initClient CredentialClientInit) *cobra.Command {
|
||||
gcmToCBC := &cobra.Command{
|
||||
Use: "gcm-to-cbc",
|
||||
Hidden: true,
|
||||
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
masterpass, cfg, err := repo.OpenConfig()
|
||||
check(err)
|
||||
|
||||
privKey := cfg.GetString(clitypes.KeyPrivateKey)
|
||||
|
||||
fmt.Println(privKey)
|
||||
|
||||
oldHex, err := hex.DecodeString(privKey)
|
||||
check(err)
|
||||
|
||||
oldKey, err := crypto.CombinePasswordAndKey([]byte(masterpass), oldHex)
|
||||
check(err)
|
||||
|
||||
key := crypto.GeneratePBKDF2Key([]byte(masterpass), []byte(privKey))
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*30)
|
||||
defer cancel()
|
||||
|
||||
client := initClient(ctx)
|
||||
|
||||
mdch, errch := client.GetAllMetadata(ctx, "")
|
||||
|
||||
receive:
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
check(ctx.Err())
|
||||
|
||||
case err := <-errch:
|
||||
check(err)
|
||||
|
||||
case md, ok := <-mdch:
|
||||
if !ok {
|
||||
break receive
|
||||
}
|
||||
|
||||
cred, err := client.Get(ctx, md.ID)
|
||||
check(err)
|
||||
|
||||
cipherpass, err := base64.StdEncoding.DecodeString(cred.Password)
|
||||
check(err)
|
||||
|
||||
plainpass, err := crypto.GCMDecrypt(oldKey, cipherpass)
|
||||
check(err)
|
||||
|
||||
cipherpass, err = crypto.CBCEncrypt(key, plainpass)
|
||||
check(err)
|
||||
|
||||
password := base64.StdEncoding.EncodeToString(cipherpass)
|
||||
|
||||
var otpSecret string
|
||||
|
||||
if cred.OTPSecret != "" {
|
||||
ciphersecret, err := base64.StdEncoding.DecodeString(cred.OTPSecret)
|
||||
check(err)
|
||||
|
||||
plainsecret, err := crypto.GCMDecrypt(oldKey, ciphersecret)
|
||||
check(err)
|
||||
|
||||
ciphersecret, err = crypto.CBCEncrypt(key, plainsecret)
|
||||
check(err)
|
||||
|
||||
otpSecret = base64.StdEncoding.EncodeToString(ciphersecret)
|
||||
}
|
||||
|
||||
credIn := types.CredentialInput{
|
||||
MetadataInput: types.MetadataInput{
|
||||
Primary: cred.Primary,
|
||||
SourceHost: cred.SourceHost,
|
||||
LoginURL: cred.LoginURL,
|
||||
Tag: cred.Tag,
|
||||
},
|
||||
Username: cred.Username,
|
||||
Email: cred.Email,
|
||||
Password: password,
|
||||
OTPSecret: otpSecret,
|
||||
}
|
||||
|
||||
_, err = client.Update(ctx, cred.ID, credIn)
|
||||
check(err)
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
return gcmToCBC
|
||||
}
|
||||
94
services/credentials/commands/get.go
Normal file
94
services/credentials/commands/get.go
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
package commands
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/atotto/clipboard"
|
||||
"github.com/pquerna/otp/totp"
|
||||
"github.com/spf13/cobra"
|
||||
"gopkg.in/AlecAivazis/survey.v1"
|
||||
|
||||
clitypes "github.com/mitchell/selfpass/services/cli/types"
|
||||
"github.com/mitchell/selfpass/services/crypto"
|
||||
)
|
||||
|
||||
func MakeGet(repo clitypes.ConfigRepo, initClient CredentialClientInit) *cobra.Command {
|
||||
getCmd := &cobra.Command{
|
||||
Use: "get",
|
||||
Short: "Get a credential info and copy password to clipboard",
|
||||
Long: `Get a credential's info and copy password to clipboard, from Selfpass server, after
|
||||
decrypting password.`,
|
||||
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
var (
|
||||
copyPass bool
|
||||
cleancb bool
|
||||
prompt survey.Prompt
|
||||
)
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*15)
|
||||
defer cancel()
|
||||
|
||||
client := initClient(ctx)
|
||||
masterpass, cfg, err := repo.OpenConfig()
|
||||
check(err)
|
||||
|
||||
cred := selectCredential(client)
|
||||
|
||||
fmt.Println(cred)
|
||||
|
||||
check(clipboard.WriteAll(string(cred.Primary)))
|
||||
|
||||
fmt.Println("Wrote primary user key to clipboard.")
|
||||
|
||||
key := cfg.GetString(clitypes.KeyPrivateKey)
|
||||
passkey := crypto.GeneratePBKDF2Key([]byte(masterpass), []byte(key))
|
||||
|
||||
prompt = &survey.Confirm{Message: "Copy password to clipboard?", Default: true}
|
||||
check(survey.AskOne(prompt, ©Pass, nil))
|
||||
|
||||
if copyPass {
|
||||
passbytes, err := base64.StdEncoding.DecodeString(cred.Password)
|
||||
check(err)
|
||||
|
||||
plainpass, err := crypto.CBCDecrypt(passkey, passbytes)
|
||||
|
||||
check(clipboard.WriteAll(string(plainpass)))
|
||||
|
||||
fmt.Println("Wrote password to clipboard.")
|
||||
}
|
||||
|
||||
if cred.OTPSecret != "" {
|
||||
var newOTP bool
|
||||
prompt = &survey.Confirm{Message: "Generate one time password and copy to clipboard?", Default: true}
|
||||
check(survey.AskOne(prompt, &newOTP, nil))
|
||||
|
||||
if newOTP {
|
||||
secretbytes, err := base64.StdEncoding.DecodeString(cred.OTPSecret)
|
||||
check(err)
|
||||
|
||||
plainsecret, err := crypto.CBCDecrypt(passkey, secretbytes)
|
||||
|
||||
otp, err := totp.GenerateCode(string(plainsecret), time.Now())
|
||||
check(err)
|
||||
|
||||
check(clipboard.WriteAll(otp))
|
||||
|
||||
fmt.Println("Wrote one time password to clipboard.")
|
||||
}
|
||||
}
|
||||
|
||||
prompt = &survey.Confirm{Message: "Do you want to clear the clipboard?", Default: true}
|
||||
check(survey.AskOne(prompt, &cleancb, nil))
|
||||
|
||||
if cleancb {
|
||||
check(clipboard.WriteAll(" "))
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
return getCmd
|
||||
}
|
||||
77
services/credentials/commands/list.go
Normal file
77
services/credentials/commands/list.go
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
package commands
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"sort"
|
||||
"time"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"gopkg.in/AlecAivazis/survey.v1"
|
||||
|
||||
"github.com/mitchell/selfpass/services/credentials/types"
|
||||
)
|
||||
|
||||
func MakeList(initClient CredentialClientInit) *cobra.Command {
|
||||
var sourceHost string
|
||||
|
||||
listCmd := &cobra.Command{
|
||||
Use: "list",
|
||||
Short: "List the metadata for all credentials",
|
||||
Long: `List the metadata for all credentials, with the option to filter by source host. Metadata
|
||||
includes almost all the information but the most sensitive.`,
|
||||
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*20)
|
||||
defer cancel()
|
||||
|
||||
mdch, errch := initClient(ctx).GetAllMetadata(ctx, sourceHost)
|
||||
mds := map[string][]types.Metadata{}
|
||||
|
||||
fmt.Println()
|
||||
|
||||
receive:
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
check(ctx.Err())
|
||||
|
||||
case err := <-errch:
|
||||
check(err)
|
||||
|
||||
case md, ok := <-mdch:
|
||||
if !ok {
|
||||
break receive
|
||||
}
|
||||
|
||||
mds[md.SourceHost] = append(mds[md.SourceHost], md)
|
||||
}
|
||||
}
|
||||
|
||||
sources := []string{}
|
||||
for source := range mds {
|
||||
sources = append(sources, source)
|
||||
}
|
||||
|
||||
sort.Strings(sources)
|
||||
|
||||
prompt := &survey.Select{
|
||||
Message: "Source host:",
|
||||
Options: sources,
|
||||
PageSize: 20,
|
||||
VimMode: true,
|
||||
}
|
||||
|
||||
var source string
|
||||
check(survey.AskOne(prompt, &source, nil))
|
||||
|
||||
for _, md := range mds[source] {
|
||||
fmt.Println(md)
|
||||
}
|
||||
|
||||
fmt.Println("Done listing.")
|
||||
},
|
||||
}
|
||||
|
||||
return listCmd
|
||||
}
|
||||
190
services/credentials/commands/update.go
Normal file
190
services/credentials/commands/update.go
Normal file
|
|
@ -0,0 +1,190 @@
|
|||
package commands
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/atotto/clipboard"
|
||||
"github.com/pquerna/otp/totp"
|
||||
"github.com/spf13/cobra"
|
||||
"gopkg.in/AlecAivazis/survey.v1"
|
||||
|
||||
clitypes "github.com/mitchell/selfpass/services/cli/types"
|
||||
"github.com/mitchell/selfpass/services/credentials/types"
|
||||
"github.com/mitchell/selfpass/services/crypto"
|
||||
)
|
||||
|
||||
func MakeUpdate(repo clitypes.ConfigRepo, initClient CredentialClientInit) *cobra.Command {
|
||||
var length uint
|
||||
var numbers bool
|
||||
var specials bool
|
||||
|
||||
updateCmd := &cobra.Command{
|
||||
Use: "update",
|
||||
Short: "Update a credential in Selfpass",
|
||||
Long: `Update a credential in Selfpass, and save it to the server after encrypting the
|
||||
password.`,
|
||||
|
||||
Run: func(_ *cobra.Command, args []string) {
|
||||
var (
|
||||
newpass bool
|
||||
otp bool
|
||||
cleancb bool
|
||||
prompt survey.Prompt
|
||||
ci types.CredentialInput
|
||||
)
|
||||
|
||||
masterpass, cfg, err := repo.OpenConfig()
|
||||
check(err)
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*15)
|
||||
defer cancel()
|
||||
|
||||
client := initClient(ctx)
|
||||
|
||||
cred := selectCredential(client)
|
||||
|
||||
mdqs := []*survey.Question{
|
||||
{
|
||||
Name: "primary",
|
||||
Prompt: &survey.Input{
|
||||
Message: "Primary user key:",
|
||||
Default: cred.Primary,
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "sourceHost",
|
||||
Prompt: &survey.Input{
|
||||
Message: "Source host:",
|
||||
Default: cred.SourceHost,
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "loginURL",
|
||||
Prompt: &survey.Input{
|
||||
Message: "Login url:",
|
||||
Default: cred.LoginURL,
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "tag",
|
||||
Prompt: &survey.Input{
|
||||
Message: "Tag:",
|
||||
Default: cred.Tag,
|
||||
},
|
||||
},
|
||||
}
|
||||
cqs := []*survey.Question{
|
||||
{
|
||||
Name: "username",
|
||||
Prompt: &survey.Input{
|
||||
Message: "Username:",
|
||||
Default: cred.Username,
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "email",
|
||||
Prompt: &survey.Input{
|
||||
Message: "Email:",
|
||||
Default: cred.Email,
|
||||
},
|
||||
},
|
||||
}
|
||||
check(survey.Ask(mdqs, &ci.MetadataInput))
|
||||
check(survey.Ask(cqs, &ci))
|
||||
|
||||
ci.Password = cred.Password
|
||||
ci.OTPSecret = cred.OTPSecret
|
||||
|
||||
key := cfg.GetString(clitypes.KeyPrivateKey)
|
||||
keypass := crypto.GeneratePBKDF2Key([]byte(masterpass), []byte(key))
|
||||
|
||||
prompt = &survey.Confirm{Message: "Do you want a new password?", Default: true}
|
||||
check(survey.AskOne(prompt, &newpass, nil))
|
||||
|
||||
if newpass {
|
||||
var randpass bool
|
||||
prompt = &survey.Confirm{Message: "Do you want a random password?", Default: true}
|
||||
check(survey.AskOne(prompt, &randpass, nil))
|
||||
|
||||
if randpass {
|
||||
ci.Password = crypto.GeneratePassword(int(length), numbers, specials)
|
||||
|
||||
var copypass bool
|
||||
prompt = &survey.Confirm{Message: "Copy new pass to clipboard?", Default: true}
|
||||
check(survey.AskOne(prompt, ©pass, nil))
|
||||
|
||||
if copypass {
|
||||
check(clipboard.WriteAll(ci.Password))
|
||||
}
|
||||
} else {
|
||||
prompt := &survey.Password{Message: "Password: "}
|
||||
check(survey.AskOne(prompt, &ci.Password, nil))
|
||||
|
||||
var cpass string
|
||||
prompt = &survey.Password{Message: "Confirm password: "}
|
||||
check(survey.AskOne(prompt, &cpass, nil))
|
||||
|
||||
if ci.Password != cpass {
|
||||
fmt.Println("passwords didn't match")
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
cipherpass, err := crypto.CBCEncrypt(keypass, []byte(ci.Password))
|
||||
check(err)
|
||||
|
||||
ci.Password = base64.StdEncoding.EncodeToString(cipherpass)
|
||||
}
|
||||
|
||||
prompt = &survey.Confirm{Message: "Do you want to set a new OTP/MFA secret?", Default: true}
|
||||
check(survey.AskOne(prompt, &otp, nil))
|
||||
|
||||
if otp {
|
||||
var secret string
|
||||
prompt := &survey.Password{Message: "OTP secret:"}
|
||||
check(survey.AskOne(prompt, &secret, nil))
|
||||
|
||||
ciphersecret, err := crypto.CBCEncrypt(keypass, []byte(secret))
|
||||
check(err)
|
||||
|
||||
ci.OTPSecret = base64.StdEncoding.EncodeToString(ciphersecret)
|
||||
|
||||
var copyotp bool
|
||||
prompt2 := &survey.Confirm{Message: "Copy new OTP to clipboard?", Default: true}
|
||||
check(survey.AskOne(prompt2, ©otp, nil))
|
||||
|
||||
if copyotp {
|
||||
otp, err := totp.GenerateCode(secret, time.Now())
|
||||
check(err)
|
||||
|
||||
check(clipboard.WriteAll(otp))
|
||||
}
|
||||
}
|
||||
|
||||
ctx, cancel = context.WithTimeout(context.Background(), time.Second*25)
|
||||
defer cancel()
|
||||
|
||||
c, err := initClient(ctx).Update(ctx, cred.ID, ci)
|
||||
check(err)
|
||||
|
||||
fmt.Println(c)
|
||||
|
||||
prompt = &survey.Confirm{Message: "Do you want to clear the clipboard?", Default: true}
|
||||
check(survey.AskOne(prompt, &cleancb, nil))
|
||||
|
||||
if cleancb {
|
||||
check(clipboard.WriteAll(" "))
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
updateCmd.Flags().BoolVarP(&numbers, "numbers", "n", true, "use numbers in the generated password")
|
||||
updateCmd.Flags().BoolVarP(&specials, "specials", "s", false, "use special characters in the generated password")
|
||||
updateCmd.Flags().UintVarP(&length, "length", "l", 32, "length of the generated password")
|
||||
|
||||
return updateCmd
|
||||
}
|
||||
78
services/credentials/endpoints/endpoints.go
Normal file
78
services/credentials/endpoints/endpoints.go
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
package endpoints
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/go-kit/kit/endpoint"
|
||||
"github.com/mitchell/selfpass/services/credentials/types"
|
||||
)
|
||||
|
||||
func MakeCreateEndpoint(svc types.Service) endpoint.Endpoint {
|
||||
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
|
||||
r := request.(types.CredentialInput)
|
||||
return svc.Create(ctx, r)
|
||||
}
|
||||
}
|
||||
|
||||
func MakeDeleteEndpoint(svc types.Service) endpoint.Endpoint {
|
||||
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
|
||||
r := request.(IDRequest)
|
||||
return nil, svc.Delete(ctx, r.ID)
|
||||
}
|
||||
}
|
||||
|
||||
func MakeGetEndpoint(svc types.Service) endpoint.Endpoint {
|
||||
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
|
||||
r := request.(IDRequest)
|
||||
return svc.Get(ctx, r.ID)
|
||||
}
|
||||
}
|
||||
|
||||
func MakeGetAllMetadataEndpoint(svc types.Service) endpoint.Endpoint {
|
||||
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
|
||||
r := request.(GetAllMetadataRequest)
|
||||
|
||||
mdch, errch := svc.GetAllMetadata(ctx, r.SourceHost)
|
||||
|
||||
return MetadataStream{
|
||||
Metadata: mdch,
|
||||
Errors: errch,
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
|
||||
func MakeUpdateEndpoint(svc types.Service) endpoint.Endpoint {
|
||||
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
|
||||
r := request.(UpdateRequest)
|
||||
return svc.Update(ctx, r.ID, r.Credential)
|
||||
}
|
||||
}
|
||||
|
||||
func MakeDumpEndpoint(svc types.Service) endpoint.Endpoint {
|
||||
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
|
||||
contents, err := svc.DumpDB(ctx)
|
||||
return DumpResponse{Contents: contents}, err
|
||||
}
|
||||
}
|
||||
|
||||
type DumpResponse struct {
|
||||
Contents []byte
|
||||
}
|
||||
|
||||
type IDRequest struct {
|
||||
ID string
|
||||
}
|
||||
|
||||
type GetAllMetadataRequest struct {
|
||||
SourceHost string
|
||||
}
|
||||
|
||||
type MetadataStream struct {
|
||||
Metadata <-chan types.Metadata
|
||||
Errors chan error
|
||||
}
|
||||
|
||||
type UpdateRequest struct {
|
||||
ID string
|
||||
Credential types.CredentialInput
|
||||
}
|
||||
114
services/credentials/middleware/logger.go
Normal file
114
services/credentials/middleware/logger.go
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
package middleware
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/go-kit/kit/log"
|
||||
"github.com/mitchell/selfpass/services/credentials/types"
|
||||
)
|
||||
|
||||
func NewServiceLogger(l log.Logger, next types.Service) ServiceLogger {
|
||||
return ServiceLogger{
|
||||
l: l,
|
||||
next: next,
|
||||
}
|
||||
}
|
||||
|
||||
type ServiceLogger struct {
|
||||
l log.Logger
|
||||
next types.Service
|
||||
}
|
||||
|
||||
func (svc ServiceLogger) GetAllMetadata(ctx context.Context, sourceHost string) (output <-chan types.Metadata, errch chan error) {
|
||||
defer func(begin time.Time) {
|
||||
_ = svc.l.Log(
|
||||
"service", "Credentials",
|
||||
"method", "GetAllMetadata",
|
||||
"input", sourceHost,
|
||||
"output", "channel",
|
||||
"err", "channel",
|
||||
"took", time.Since(begin),
|
||||
)
|
||||
}(time.Now())
|
||||
|
||||
return svc.next.GetAllMetadata(ctx, sourceHost)
|
||||
}
|
||||
|
||||
func (svc ServiceLogger) Get(ctx context.Context, id string) (output types.Credential, err error) {
|
||||
defer func(begin time.Time) {
|
||||
_ = svc.l.Log(
|
||||
"service", "Credentials",
|
||||
"method", "Get",
|
||||
"input", id,
|
||||
"output", output,
|
||||
"err", err,
|
||||
"took", time.Since(begin),
|
||||
)
|
||||
}(time.Now())
|
||||
|
||||
output, err = svc.next.Get(ctx, id)
|
||||
return output, err
|
||||
}
|
||||
|
||||
func (svc ServiceLogger) Create(ctx context.Context, ci types.CredentialInput) (output types.Credential, err error) {
|
||||
defer func(begin time.Time) {
|
||||
_ = svc.l.Log(
|
||||
"service", "Credentials",
|
||||
"method", "Create",
|
||||
"input", ci,
|
||||
"output", output,
|
||||
"err", err,
|
||||
"took", time.Since(begin),
|
||||
)
|
||||
}(time.Now())
|
||||
|
||||
output, err = svc.next.Create(ctx, ci)
|
||||
return output, err
|
||||
}
|
||||
|
||||
func (svc ServiceLogger) Update(ctx context.Context, id string, ci types.CredentialInput) (output types.Credential, err error) {
|
||||
defer func(begin time.Time) {
|
||||
_ = svc.l.Log(
|
||||
"service", "Credentials",
|
||||
"method", "Update",
|
||||
"input", []interface{}{id, ci},
|
||||
"output", output,
|
||||
"err", err,
|
||||
"took", time.Since(begin),
|
||||
)
|
||||
}(time.Now())
|
||||
|
||||
output, err = svc.next.Update(ctx, id, ci)
|
||||
return output, err
|
||||
}
|
||||
|
||||
func (svc ServiceLogger) Delete(ctx context.Context, id string) (err error) {
|
||||
defer func(begin time.Time) {
|
||||
_ = svc.l.Log(
|
||||
"service", "Credentials",
|
||||
"method", "Delete",
|
||||
"input", id,
|
||||
"err", err,
|
||||
"took", time.Since(begin),
|
||||
)
|
||||
}(time.Now())
|
||||
|
||||
err = svc.next.Delete(ctx, id)
|
||||
return err
|
||||
}
|
||||
|
||||
func (svc ServiceLogger) DumpDB(ctx context.Context) (output []byte, err error) {
|
||||
defer func(begin time.Time) {
|
||||
_ = svc.l.Log(
|
||||
"service", "Credentials",
|
||||
"method", "Dump",
|
||||
"output", output,
|
||||
"err", err,
|
||||
"took", time.Since(begin),
|
||||
)
|
||||
}(time.Now())
|
||||
|
||||
output, err = svc.next.DumpDB(ctx)
|
||||
return output, err
|
||||
}
|
||||
867
services/credentials/protobuf/service.pb.go
Normal file
867
services/credentials/protobuf/service.pb.go
Normal file
|
|
@ -0,0 +1,867 @@
|
|||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// source: credentials/protobuf/service.proto
|
||||
|
||||
package protobuf
|
||||
|
||||
import (
|
||||
context "context"
|
||||
fmt "fmt"
|
||||
proto "github.com/golang/protobuf/proto"
|
||||
timestamp "github.com/golang/protobuf/ptypes/timestamp"
|
||||
grpc "google.golang.org/grpc"
|
||||
codes "google.golang.org/grpc/codes"
|
||||
status "google.golang.org/grpc/status"
|
||||
math "math"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
|
||||
|
||||
type DeleteResponse struct {
|
||||
Success bool `protobuf:"varint,1,opt,name=success,proto3" json:"success,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *DeleteResponse) Reset() { *m = DeleteResponse{} }
|
||||
func (m *DeleteResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*DeleteResponse) ProtoMessage() {}
|
||||
func (*DeleteResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_ad34efc7bbd96e69, []int{0}
|
||||
}
|
||||
|
||||
func (m *DeleteResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_DeleteResponse.Unmarshal(m, b)
|
||||
}
|
||||
func (m *DeleteResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_DeleteResponse.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *DeleteResponse) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_DeleteResponse.Merge(m, src)
|
||||
}
|
||||
func (m *DeleteResponse) XXX_Size() int {
|
||||
return xxx_messageInfo_DeleteResponse.Size(m)
|
||||
}
|
||||
func (m *DeleteResponse) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_DeleteResponse.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_DeleteResponse proto.InternalMessageInfo
|
||||
|
||||
func (m *DeleteResponse) GetSuccess() bool {
|
||||
if m != nil {
|
||||
return m.Success
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type GetAllMetadataRequest struct {
|
||||
SourceHost string `protobuf:"bytes,1,opt,name=source_host,json=sourceHost,proto3" json:"source_host,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *GetAllMetadataRequest) Reset() { *m = GetAllMetadataRequest{} }
|
||||
func (m *GetAllMetadataRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*GetAllMetadataRequest) ProtoMessage() {}
|
||||
func (*GetAllMetadataRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_ad34efc7bbd96e69, []int{1}
|
||||
}
|
||||
|
||||
func (m *GetAllMetadataRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_GetAllMetadataRequest.Unmarshal(m, b)
|
||||
}
|
||||
func (m *GetAllMetadataRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_GetAllMetadataRequest.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *GetAllMetadataRequest) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_GetAllMetadataRequest.Merge(m, src)
|
||||
}
|
||||
func (m *GetAllMetadataRequest) XXX_Size() int {
|
||||
return xxx_messageInfo_GetAllMetadataRequest.Size(m)
|
||||
}
|
||||
func (m *GetAllMetadataRequest) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_GetAllMetadataRequest.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_GetAllMetadataRequest proto.InternalMessageInfo
|
||||
|
||||
func (m *GetAllMetadataRequest) GetSourceHost() string {
|
||||
if m != nil {
|
||||
return m.SourceHost
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type IdRequest struct {
|
||||
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *IdRequest) Reset() { *m = IdRequest{} }
|
||||
func (m *IdRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*IdRequest) ProtoMessage() {}
|
||||
func (*IdRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_ad34efc7bbd96e69, []int{2}
|
||||
}
|
||||
|
||||
func (m *IdRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_IdRequest.Unmarshal(m, b)
|
||||
}
|
||||
func (m *IdRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_IdRequest.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *IdRequest) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_IdRequest.Merge(m, src)
|
||||
}
|
||||
func (m *IdRequest) XXX_Size() int {
|
||||
return xxx_messageInfo_IdRequest.Size(m)
|
||||
}
|
||||
func (m *IdRequest) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_IdRequest.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_IdRequest proto.InternalMessageInfo
|
||||
|
||||
func (m *IdRequest) GetId() string {
|
||||
if m != nil {
|
||||
return m.Id
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type UpdateRequest struct {
|
||||
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
|
||||
Credential *CredentialRequest `protobuf:"bytes,2,opt,name=credential,proto3" json:"credential,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *UpdateRequest) Reset() { *m = UpdateRequest{} }
|
||||
func (m *UpdateRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*UpdateRequest) ProtoMessage() {}
|
||||
func (*UpdateRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_ad34efc7bbd96e69, []int{3}
|
||||
}
|
||||
|
||||
func (m *UpdateRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_UpdateRequest.Unmarshal(m, b)
|
||||
}
|
||||
func (m *UpdateRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_UpdateRequest.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *UpdateRequest) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_UpdateRequest.Merge(m, src)
|
||||
}
|
||||
func (m *UpdateRequest) XXX_Size() int {
|
||||
return xxx_messageInfo_UpdateRequest.Size(m)
|
||||
}
|
||||
func (m *UpdateRequest) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_UpdateRequest.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_UpdateRequest proto.InternalMessageInfo
|
||||
|
||||
func (m *UpdateRequest) GetId() string {
|
||||
if m != nil {
|
||||
return m.Id
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *UpdateRequest) GetCredential() *CredentialRequest {
|
||||
if m != nil {
|
||||
return m.Credential
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type DumpResponse struct {
|
||||
Contents []byte `protobuf:"bytes,1,opt,name=contents,proto3" json:"contents,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *DumpResponse) Reset() { *m = DumpResponse{} }
|
||||
func (m *DumpResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*DumpResponse) ProtoMessage() {}
|
||||
func (*DumpResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_ad34efc7bbd96e69, []int{4}
|
||||
}
|
||||
|
||||
func (m *DumpResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_DumpResponse.Unmarshal(m, b)
|
||||
}
|
||||
func (m *DumpResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_DumpResponse.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *DumpResponse) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_DumpResponse.Merge(m, src)
|
||||
}
|
||||
func (m *DumpResponse) XXX_Size() int {
|
||||
return xxx_messageInfo_DumpResponse.Size(m)
|
||||
}
|
||||
func (m *DumpResponse) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_DumpResponse.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_DumpResponse proto.InternalMessageInfo
|
||||
|
||||
func (m *DumpResponse) GetContents() []byte {
|
||||
if m != nil {
|
||||
return m.Contents
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type EmptyRequest struct {
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *EmptyRequest) Reset() { *m = EmptyRequest{} }
|
||||
func (m *EmptyRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*EmptyRequest) ProtoMessage() {}
|
||||
func (*EmptyRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_ad34efc7bbd96e69, []int{5}
|
||||
}
|
||||
|
||||
func (m *EmptyRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_EmptyRequest.Unmarshal(m, b)
|
||||
}
|
||||
func (m *EmptyRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_EmptyRequest.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *EmptyRequest) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_EmptyRequest.Merge(m, src)
|
||||
}
|
||||
func (m *EmptyRequest) XXX_Size() int {
|
||||
return xxx_messageInfo_EmptyRequest.Size(m)
|
||||
}
|
||||
func (m *EmptyRequest) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_EmptyRequest.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_EmptyRequest proto.InternalMessageInfo
|
||||
|
||||
type Metadata struct {
|
||||
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
|
||||
CreatedAt *timestamp.Timestamp `protobuf:"bytes,2,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"`
|
||||
UpdatedAt *timestamp.Timestamp `protobuf:"bytes,3,opt,name=updated_at,json=updatedAt,proto3" json:"updated_at,omitempty"`
|
||||
Primary string `protobuf:"bytes,4,opt,name=primary,proto3" json:"primary,omitempty"`
|
||||
SourceHost string `protobuf:"bytes,5,opt,name=source_host,json=sourceHost,proto3" json:"source_host,omitempty"`
|
||||
LoginUrl string `protobuf:"bytes,6,opt,name=login_url,json=loginUrl,proto3" json:"login_url,omitempty"`
|
||||
Tag string `protobuf:"bytes,7,opt,name=tag,proto3" json:"tag,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *Metadata) Reset() { *m = Metadata{} }
|
||||
func (m *Metadata) String() string { return proto.CompactTextString(m) }
|
||||
func (*Metadata) ProtoMessage() {}
|
||||
func (*Metadata) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_ad34efc7bbd96e69, []int{6}
|
||||
}
|
||||
|
||||
func (m *Metadata) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_Metadata.Unmarshal(m, b)
|
||||
}
|
||||
func (m *Metadata) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_Metadata.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *Metadata) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_Metadata.Merge(m, src)
|
||||
}
|
||||
func (m *Metadata) XXX_Size() int {
|
||||
return xxx_messageInfo_Metadata.Size(m)
|
||||
}
|
||||
func (m *Metadata) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_Metadata.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_Metadata proto.InternalMessageInfo
|
||||
|
||||
func (m *Metadata) GetId() string {
|
||||
if m != nil {
|
||||
return m.Id
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *Metadata) GetCreatedAt() *timestamp.Timestamp {
|
||||
if m != nil {
|
||||
return m.CreatedAt
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Metadata) GetUpdatedAt() *timestamp.Timestamp {
|
||||
if m != nil {
|
||||
return m.UpdatedAt
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Metadata) GetPrimary() string {
|
||||
if m != nil {
|
||||
return m.Primary
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *Metadata) GetSourceHost() string {
|
||||
if m != nil {
|
||||
return m.SourceHost
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *Metadata) GetLoginUrl() string {
|
||||
if m != nil {
|
||||
return m.LoginUrl
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *Metadata) GetTag() string {
|
||||
if m != nil {
|
||||
return m.Tag
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type Credential struct {
|
||||
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
|
||||
CreatedAt *timestamp.Timestamp `protobuf:"bytes,2,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"`
|
||||
UpdatedAt *timestamp.Timestamp `protobuf:"bytes,3,opt,name=updated_at,json=updatedAt,proto3" json:"updated_at,omitempty"`
|
||||
Primary string `protobuf:"bytes,4,opt,name=primary,proto3" json:"primary,omitempty"`
|
||||
Username string `protobuf:"bytes,5,opt,name=username,proto3" json:"username,omitempty"`
|
||||
Email string `protobuf:"bytes,6,opt,name=email,proto3" json:"email,omitempty"`
|
||||
Password string `protobuf:"bytes,7,opt,name=password,proto3" json:"password,omitempty"`
|
||||
SourceHost string `protobuf:"bytes,8,opt,name=source_host,json=sourceHost,proto3" json:"source_host,omitempty"`
|
||||
LoginUrl string `protobuf:"bytes,9,opt,name=login_url,json=loginUrl,proto3" json:"login_url,omitempty"`
|
||||
Tag string `protobuf:"bytes,10,opt,name=tag,proto3" json:"tag,omitempty"`
|
||||
OtpSecret string `protobuf:"bytes,11,opt,name=otp_secret,json=otpSecret,proto3" json:"otp_secret,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *Credential) Reset() { *m = Credential{} }
|
||||
func (m *Credential) String() string { return proto.CompactTextString(m) }
|
||||
func (*Credential) ProtoMessage() {}
|
||||
func (*Credential) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_ad34efc7bbd96e69, []int{7}
|
||||
}
|
||||
|
||||
func (m *Credential) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_Credential.Unmarshal(m, b)
|
||||
}
|
||||
func (m *Credential) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_Credential.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *Credential) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_Credential.Merge(m, src)
|
||||
}
|
||||
func (m *Credential) XXX_Size() int {
|
||||
return xxx_messageInfo_Credential.Size(m)
|
||||
}
|
||||
func (m *Credential) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_Credential.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_Credential proto.InternalMessageInfo
|
||||
|
||||
func (m *Credential) GetId() string {
|
||||
if m != nil {
|
||||
return m.Id
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *Credential) GetCreatedAt() *timestamp.Timestamp {
|
||||
if m != nil {
|
||||
return m.CreatedAt
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Credential) GetUpdatedAt() *timestamp.Timestamp {
|
||||
if m != nil {
|
||||
return m.UpdatedAt
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Credential) GetPrimary() string {
|
||||
if m != nil {
|
||||
return m.Primary
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *Credential) GetUsername() string {
|
||||
if m != nil {
|
||||
return m.Username
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *Credential) GetEmail() string {
|
||||
if m != nil {
|
||||
return m.Email
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *Credential) GetPassword() string {
|
||||
if m != nil {
|
||||
return m.Password
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *Credential) GetSourceHost() string {
|
||||
if m != nil {
|
||||
return m.SourceHost
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *Credential) GetLoginUrl() string {
|
||||
if m != nil {
|
||||
return m.LoginUrl
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *Credential) GetTag() string {
|
||||
if m != nil {
|
||||
return m.Tag
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *Credential) GetOtpSecret() string {
|
||||
if m != nil {
|
||||
return m.OtpSecret
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type CredentialRequest struct {
|
||||
Primary string `protobuf:"bytes,1,opt,name=primary,proto3" json:"primary,omitempty"`
|
||||
Username string `protobuf:"bytes,2,opt,name=username,proto3" json:"username,omitempty"`
|
||||
Email string `protobuf:"bytes,3,opt,name=email,proto3" json:"email,omitempty"`
|
||||
Password string `protobuf:"bytes,4,opt,name=password,proto3" json:"password,omitempty"`
|
||||
SourceHost string `protobuf:"bytes,5,opt,name=source_host,json=sourceHost,proto3" json:"source_host,omitempty"`
|
||||
LoginUrl string `protobuf:"bytes,6,opt,name=login_url,json=loginUrl,proto3" json:"login_url,omitempty"`
|
||||
Tag string `protobuf:"bytes,7,opt,name=tag,proto3" json:"tag,omitempty"`
|
||||
OtpSecret string `protobuf:"bytes,8,opt,name=otp_secret,json=otpSecret,proto3" json:"otp_secret,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *CredentialRequest) Reset() { *m = CredentialRequest{} }
|
||||
func (m *CredentialRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*CredentialRequest) ProtoMessage() {}
|
||||
func (*CredentialRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_ad34efc7bbd96e69, []int{8}
|
||||
}
|
||||
|
||||
func (m *CredentialRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_CredentialRequest.Unmarshal(m, b)
|
||||
}
|
||||
func (m *CredentialRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_CredentialRequest.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *CredentialRequest) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_CredentialRequest.Merge(m, src)
|
||||
}
|
||||
func (m *CredentialRequest) XXX_Size() int {
|
||||
return xxx_messageInfo_CredentialRequest.Size(m)
|
||||
}
|
||||
func (m *CredentialRequest) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_CredentialRequest.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_CredentialRequest proto.InternalMessageInfo
|
||||
|
||||
func (m *CredentialRequest) GetPrimary() string {
|
||||
if m != nil {
|
||||
return m.Primary
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *CredentialRequest) GetUsername() string {
|
||||
if m != nil {
|
||||
return m.Username
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *CredentialRequest) GetEmail() string {
|
||||
if m != nil {
|
||||
return m.Email
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *CredentialRequest) GetPassword() string {
|
||||
if m != nil {
|
||||
return m.Password
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *CredentialRequest) GetSourceHost() string {
|
||||
if m != nil {
|
||||
return m.SourceHost
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *CredentialRequest) GetLoginUrl() string {
|
||||
if m != nil {
|
||||
return m.LoginUrl
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *CredentialRequest) GetTag() string {
|
||||
if m != nil {
|
||||
return m.Tag
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *CredentialRequest) GetOtpSecret() string {
|
||||
if m != nil {
|
||||
return m.OtpSecret
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*DeleteResponse)(nil), "selfpass.credentials.DeleteResponse")
|
||||
proto.RegisterType((*GetAllMetadataRequest)(nil), "selfpass.credentials.GetAllMetadataRequest")
|
||||
proto.RegisterType((*IdRequest)(nil), "selfpass.credentials.IdRequest")
|
||||
proto.RegisterType((*UpdateRequest)(nil), "selfpass.credentials.UpdateRequest")
|
||||
proto.RegisterType((*DumpResponse)(nil), "selfpass.credentials.DumpResponse")
|
||||
proto.RegisterType((*EmptyRequest)(nil), "selfpass.credentials.EmptyRequest")
|
||||
proto.RegisterType((*Metadata)(nil), "selfpass.credentials.Metadata")
|
||||
proto.RegisterType((*Credential)(nil), "selfpass.credentials.Credential")
|
||||
proto.RegisterType((*CredentialRequest)(nil), "selfpass.credentials.CredentialRequest")
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("credentials/protobuf/service.proto", fileDescriptor_ad34efc7bbd96e69) }
|
||||
|
||||
var fileDescriptor_ad34efc7bbd96e69 = []byte{
|
||||
// 561 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x95, 0x4d, 0x6f, 0xd3, 0x4c,
|
||||
0x10, 0xc7, 0xe5, 0xa4, 0x4d, 0xed, 0x69, 0x9f, 0xe8, 0x61, 0x55, 0x24, 0xcb, 0x15, 0x24, 0x32,
|
||||
0x48, 0x54, 0x45, 0x72, 0x51, 0xb9, 0xc0, 0x31, 0xb4, 0x28, 0xe5, 0x80, 0x90, 0x1c, 0x7a, 0xe1,
|
||||
0x12, 0x6d, 0xed, 0x69, 0x6a, 0xc9, 0xf6, 0x9a, 0xdd, 0x31, 0xa8, 0x1f, 0x8c, 0x0f, 0x05, 0x1f,
|
||||
0x81, 0x13, 0xf2, 0xfa, 0x25, 0x2f, 0x75, 0x9a, 0x48, 0x5c, 0xb8, 0xed, 0x8c, 0xff, 0xb3, 0x9a,
|
||||
0xdf, 0xec, 0xee, 0xdf, 0xe0, 0x06, 0x12, 0x43, 0x4c, 0x29, 0xe2, 0xb1, 0x3a, 0xcd, 0xa4, 0x20,
|
||||
0x71, 0x9d, 0xdf, 0x9c, 0x2a, 0x94, 0xdf, 0xa2, 0x00, 0x3d, 0x9d, 0x60, 0x87, 0x0a, 0xe3, 0x9b,
|
||||
0x8c, 0x2b, 0xe5, 0x2d, 0x88, 0x9d, 0xc1, 0x4c, 0x88, 0x59, 0x8c, 0xf3, 0x22, 0x8a, 0x12, 0x54,
|
||||
0xc4, 0x93, 0xac, 0x2c, 0x73, 0x4f, 0xa0, 0x7f, 0x81, 0x31, 0x12, 0xfa, 0xa8, 0x32, 0x91, 0x2a,
|
||||
0x64, 0x36, 0xec, 0xa9, 0x3c, 0x08, 0x50, 0x29, 0xdb, 0x18, 0x1a, 0xc7, 0xa6, 0x5f, 0x87, 0xee,
|
||||
0x1b, 0x78, 0x3c, 0x46, 0x1a, 0xc5, 0xf1, 0x47, 0x24, 0x1e, 0x72, 0xe2, 0x3e, 0x7e, 0xcd, 0x51,
|
||||
0x11, 0x1b, 0xc0, 0xbe, 0x12, 0xb9, 0x0c, 0x70, 0x7a, 0x2b, 0x14, 0xe9, 0x32, 0xcb, 0x87, 0x32,
|
||||
0x75, 0x29, 0x14, 0xb9, 0x47, 0x60, 0x7d, 0x08, 0x6b, 0x75, 0x1f, 0x3a, 0x51, 0x58, 0x89, 0x3a,
|
||||
0x51, 0xe8, 0xde, 0xc2, 0x7f, 0x57, 0x59, 0xc8, 0x8b, 0x16, 0x5a, 0x05, 0x6c, 0x0c, 0x30, 0x67,
|
||||
0xb2, 0x3b, 0x43, 0xe3, 0x78, 0xff, 0xec, 0x85, 0xd7, 0xc6, 0xeb, 0x9d, 0x37, 0xeb, 0x6a, 0x33,
|
||||
0x7f, 0xa1, 0xd4, 0x3d, 0x81, 0x83, 0x8b, 0x3c, 0xc9, 0x1a, 0x54, 0x07, 0xcc, 0x40, 0xa4, 0x84,
|
||||
0x29, 0x95, 0xac, 0x07, 0x7e, 0x13, 0xbb, 0x7d, 0x38, 0x78, 0x9f, 0x64, 0x74, 0x57, 0xed, 0xe3,
|
||||
0xfe, 0x36, 0xc0, 0xac, 0xb9, 0xef, 0x75, 0xf8, 0x56, 0x77, 0xc8, 0x09, 0xc3, 0x29, 0xa7, 0xaa,
|
||||
0x43, 0xc7, 0x2b, 0x67, 0xef, 0xd5, 0xb3, 0xf7, 0x3e, 0xd7, 0xb3, 0xf7, 0xad, 0x4a, 0x3d, 0xa2,
|
||||
0xa2, 0x34, 0xd7, 0xf4, 0xba, 0xb4, 0xbb, 0xb9, 0xb4, 0x52, 0x8f, 0xa8, 0x38, 0xa9, 0x4c, 0x46,
|
||||
0x09, 0x97, 0x77, 0xf6, 0x8e, 0x6e, 0xa5, 0x0e, 0x57, 0x0f, 0x64, 0x77, 0xf5, 0x40, 0xd8, 0x11,
|
||||
0x58, 0xb1, 0x98, 0x45, 0xe9, 0x34, 0x97, 0xb1, 0xdd, 0xd3, 0x9f, 0x4d, 0x9d, 0xb8, 0x92, 0x31,
|
||||
0xfb, 0x1f, 0xba, 0xc4, 0x67, 0xf6, 0x9e, 0x4e, 0x17, 0x4b, 0xf7, 0x67, 0x07, 0x60, 0x3e, 0xda,
|
||||
0x7f, 0x1e, 0xdf, 0x01, 0x33, 0x57, 0x28, 0x53, 0x9e, 0x60, 0xc5, 0xde, 0xc4, 0xec, 0x10, 0x76,
|
||||
0x31, 0xe1, 0x51, 0x4d, 0x5d, 0x06, 0x45, 0x45, 0x71, 0x97, 0xbe, 0x0b, 0x19, 0x56, 0xdc, 0x4d,
|
||||
0xbc, 0x3a, 0x4c, 0xf3, 0xe1, 0x61, 0x5a, 0xed, 0xc3, 0x84, 0x66, 0x98, 0xec, 0x09, 0x80, 0xa0,
|
||||
0x6c, 0xaa, 0x30, 0x90, 0x48, 0xf6, 0xbe, 0xfe, 0x60, 0x09, 0xca, 0x26, 0x3a, 0xe1, 0xfe, 0x32,
|
||||
0xe0, 0xd1, 0xbd, 0x6b, 0xbc, 0x08, 0x6b, 0xac, 0x87, 0xed, 0xac, 0x83, 0xed, 0xae, 0x83, 0xdd,
|
||||
0x79, 0x18, 0xf6, 0x6f, 0x6f, 0xce, 0x0a, 0xac, 0xb9, 0x02, 0x7b, 0xf6, 0xa3, 0xbb, 0x08, 0x3b,
|
||||
0x29, 0x1d, 0x8d, 0x4d, 0xa1, 0xbf, 0x6c, 0x34, 0xec, 0x65, 0xfb, 0x73, 0x6f, 0xb5, 0x23, 0xe7,
|
||||
0x69, 0xbb, 0xb8, 0x96, 0xbd, 0x32, 0xd8, 0x25, 0x74, 0xc7, 0x48, 0x6c, 0xd0, 0x2e, 0x6c, 0xac,
|
||||
0xca, 0x19, 0x6e, 0x72, 0x19, 0x36, 0x81, 0xde, 0xb9, 0xbe, 0xcc, 0x6c, 0x5b, 0x47, 0xda, 0x62,
|
||||
0xd3, 0x4f, 0xd0, 0x2b, 0x1d, 0x91, 0x3d, 0x6b, 0xd7, 0x2e, 0xf9, 0xe5, 0x76, 0x1b, 0x96, 0x2e,
|
||||
0xbf, 0x19, 0xf9, 0x79, 0xbb, 0x60, 0xf9, 0x27, 0xf1, 0x0e, 0xbe, 0x98, 0xf5, 0xe3, 0xbc, 0xee,
|
||||
0xe9, 0xd5, 0xeb, 0x3f, 0x01, 0x00, 0x00, 0xff, 0xff, 0xde, 0x03, 0x4f, 0xb2, 0xa6, 0x06, 0x00,
|
||||
0x00,
|
||||
}
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ context.Context
|
||||
var _ grpc.ClientConn
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the grpc package it is being compiled against.
|
||||
const _ = grpc.SupportPackageIsVersion4
|
||||
|
||||
// CredentialServiceClient is the client API for CredentialService service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
|
||||
type CredentialServiceClient interface {
|
||||
GetAllMetadata(ctx context.Context, in *GetAllMetadataRequest, opts ...grpc.CallOption) (CredentialService_GetAllMetadataClient, error)
|
||||
Get(ctx context.Context, in *IdRequest, opts ...grpc.CallOption) (*Credential, error)
|
||||
Create(ctx context.Context, in *CredentialRequest, opts ...grpc.CallOption) (*Credential, error)
|
||||
Update(ctx context.Context, in *UpdateRequest, opts ...grpc.CallOption) (*Credential, error)
|
||||
Delete(ctx context.Context, in *IdRequest, opts ...grpc.CallOption) (*DeleteResponse, error)
|
||||
}
|
||||
|
||||
type credentialServiceClient struct {
|
||||
cc *grpc.ClientConn
|
||||
}
|
||||
|
||||
func NewCredentialServiceClient(cc *grpc.ClientConn) CredentialServiceClient {
|
||||
return &credentialServiceClient{cc}
|
||||
}
|
||||
|
||||
func (c *credentialServiceClient) GetAllMetadata(ctx context.Context, in *GetAllMetadataRequest, opts ...grpc.CallOption) (CredentialService_GetAllMetadataClient, error) {
|
||||
stream, err := c.cc.NewStream(ctx, &_CredentialService_serviceDesc.Streams[0], "/selfpass.credentials.CredentialService/GetAllMetadata", opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
x := &credentialServiceGetAllMetadataClient{stream}
|
||||
if err := x.ClientStream.SendMsg(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := x.ClientStream.CloseSend(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return x, nil
|
||||
}
|
||||
|
||||
type CredentialService_GetAllMetadataClient interface {
|
||||
Recv() (*Metadata, error)
|
||||
grpc.ClientStream
|
||||
}
|
||||
|
||||
type credentialServiceGetAllMetadataClient struct {
|
||||
grpc.ClientStream
|
||||
}
|
||||
|
||||
func (x *credentialServiceGetAllMetadataClient) Recv() (*Metadata, error) {
|
||||
m := new(Metadata)
|
||||
if err := x.ClientStream.RecvMsg(m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func (c *credentialServiceClient) Get(ctx context.Context, in *IdRequest, opts ...grpc.CallOption) (*Credential, error) {
|
||||
out := new(Credential)
|
||||
err := c.cc.Invoke(ctx, "/selfpass.credentials.CredentialService/Get", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *credentialServiceClient) Create(ctx context.Context, in *CredentialRequest, opts ...grpc.CallOption) (*Credential, error) {
|
||||
out := new(Credential)
|
||||
err := c.cc.Invoke(ctx, "/selfpass.credentials.CredentialService/Create", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *credentialServiceClient) Update(ctx context.Context, in *UpdateRequest, opts ...grpc.CallOption) (*Credential, error) {
|
||||
out := new(Credential)
|
||||
err := c.cc.Invoke(ctx, "/selfpass.credentials.CredentialService/Update", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *credentialServiceClient) Delete(ctx context.Context, in *IdRequest, opts ...grpc.CallOption) (*DeleteResponse, error) {
|
||||
out := new(DeleteResponse)
|
||||
err := c.cc.Invoke(ctx, "/selfpass.credentials.CredentialService/Delete", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// CredentialServiceServer is the server API for CredentialService service.
|
||||
type CredentialServiceServer interface {
|
||||
GetAllMetadata(*GetAllMetadataRequest, CredentialService_GetAllMetadataServer) error
|
||||
Get(context.Context, *IdRequest) (*Credential, error)
|
||||
Create(context.Context, *CredentialRequest) (*Credential, error)
|
||||
Update(context.Context, *UpdateRequest) (*Credential, error)
|
||||
Delete(context.Context, *IdRequest) (*DeleteResponse, error)
|
||||
}
|
||||
|
||||
// UnimplementedCredentialServiceServer can be embedded to have forward compatible implementations.
|
||||
type UnimplementedCredentialServiceServer struct {
|
||||
}
|
||||
|
||||
func (*UnimplementedCredentialServiceServer) GetAllMetadata(req *GetAllMetadataRequest, srv CredentialService_GetAllMetadataServer) error {
|
||||
return status.Errorf(codes.Unimplemented, "method GetAllMetadata not implemented")
|
||||
}
|
||||
func (*UnimplementedCredentialServiceServer) Get(ctx context.Context, req *IdRequest) (*Credential, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Get not implemented")
|
||||
}
|
||||
func (*UnimplementedCredentialServiceServer) Create(ctx context.Context, req *CredentialRequest) (*Credential, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Create not implemented")
|
||||
}
|
||||
func (*UnimplementedCredentialServiceServer) Update(ctx context.Context, req *UpdateRequest) (*Credential, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Update not implemented")
|
||||
}
|
||||
func (*UnimplementedCredentialServiceServer) Delete(ctx context.Context, req *IdRequest) (*DeleteResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Delete not implemented")
|
||||
}
|
||||
|
||||
func RegisterCredentialServiceServer(s *grpc.Server, srv CredentialServiceServer) {
|
||||
s.RegisterService(&_CredentialService_serviceDesc, srv)
|
||||
}
|
||||
|
||||
func _CredentialService_GetAllMetadata_Handler(srv interface{}, stream grpc.ServerStream) error {
|
||||
m := new(GetAllMetadataRequest)
|
||||
if err := stream.RecvMsg(m); err != nil {
|
||||
return err
|
||||
}
|
||||
return srv.(CredentialServiceServer).GetAllMetadata(m, &credentialServiceGetAllMetadataServer{stream})
|
||||
}
|
||||
|
||||
type CredentialService_GetAllMetadataServer interface {
|
||||
Send(*Metadata) error
|
||||
grpc.ServerStream
|
||||
}
|
||||
|
||||
type credentialServiceGetAllMetadataServer struct {
|
||||
grpc.ServerStream
|
||||
}
|
||||
|
||||
func (x *credentialServiceGetAllMetadataServer) Send(m *Metadata) error {
|
||||
return x.ServerStream.SendMsg(m)
|
||||
}
|
||||
|
||||
func _CredentialService_Get_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(IdRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(CredentialServiceServer).Get(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/selfpass.credentials.CredentialService/Get",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(CredentialServiceServer).Get(ctx, req.(*IdRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _CredentialService_Create_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(CredentialRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(CredentialServiceServer).Create(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/selfpass.credentials.CredentialService/Create",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(CredentialServiceServer).Create(ctx, req.(*CredentialRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _CredentialService_Update_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(UpdateRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(CredentialServiceServer).Update(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/selfpass.credentials.CredentialService/Update",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(CredentialServiceServer).Update(ctx, req.(*UpdateRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _CredentialService_Delete_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(IdRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(CredentialServiceServer).Delete(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/selfpass.credentials.CredentialService/Delete",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(CredentialServiceServer).Delete(ctx, req.(*IdRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
var _CredentialService_serviceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "selfpass.credentials.CredentialService",
|
||||
HandlerType: (*CredentialServiceServer)(nil),
|
||||
Methods: []grpc.MethodDesc{
|
||||
{
|
||||
MethodName: "Get",
|
||||
Handler: _CredentialService_Get_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "Create",
|
||||
Handler: _CredentialService_Create_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "Update",
|
||||
Handler: _CredentialService_Update_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "Delete",
|
||||
Handler: _CredentialService_Delete_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{
|
||||
{
|
||||
StreamName: "GetAllMetadata",
|
||||
Handler: _CredentialService_GetAllMetadata_Handler,
|
||||
ServerStreams: true,
|
||||
},
|
||||
},
|
||||
Metadata: "credentials/protobuf/service.proto",
|
||||
}
|
||||
75
services/credentials/protobuf/service.proto
Normal file
75
services/credentials/protobuf/service.proto
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
syntax = "proto3";
|
||||
|
||||
package selfpass.credentials;
|
||||
|
||||
option go_package = "protobuf";
|
||||
|
||||
import "google/protobuf/timestamp.proto";
|
||||
|
||||
service CredentialService {
|
||||
rpc GetAllMetadata (GetAllMetadataRequest) returns (stream Metadata);
|
||||
rpc Get (IdRequest) returns (Credential);
|
||||
rpc Create (CredentialRequest) returns (Credential);
|
||||
rpc Update (UpdateRequest) returns (Credential);
|
||||
rpc Delete (IdRequest) returns (DeleteResponse);
|
||||
// rpc Dump (EmptyRequest) returns (DumpResponse);
|
||||
}
|
||||
|
||||
message DeleteResponse {
|
||||
bool success = 1;
|
||||
}
|
||||
|
||||
message GetAllMetadataRequest {
|
||||
string source_host = 1;
|
||||
}
|
||||
|
||||
message IdRequest {
|
||||
string id = 1;
|
||||
}
|
||||
|
||||
message UpdateRequest {
|
||||
string id = 1;
|
||||
CredentialRequest credential = 2;
|
||||
}
|
||||
|
||||
message DumpResponse {
|
||||
bytes contents = 1;
|
||||
}
|
||||
|
||||
message EmptyRequest {
|
||||
}
|
||||
|
||||
message Metadata {
|
||||
string id = 1;
|
||||
google.protobuf.Timestamp created_at = 2;
|
||||
google.protobuf.Timestamp updated_at = 3;
|
||||
string primary = 4;
|
||||
string source_host = 5;
|
||||
string login_url = 6;
|
||||
string tag = 7;
|
||||
}
|
||||
|
||||
message Credential {
|
||||
string id = 1;
|
||||
google.protobuf.Timestamp created_at = 2;
|
||||
google.protobuf.Timestamp updated_at = 3;
|
||||
string primary = 4;
|
||||
string username = 5;
|
||||
string email = 6;
|
||||
string password = 7;
|
||||
string source_host = 8;
|
||||
string login_url = 9;
|
||||
string tag = 10;
|
||||
string otp_secret = 11;
|
||||
}
|
||||
|
||||
message CredentialRequest {
|
||||
string primary = 1;
|
||||
string username = 2;
|
||||
string email = 3;
|
||||
string password = 4;
|
||||
string source_host = 5;
|
||||
string login_url = 6;
|
||||
string tag = 7;
|
||||
string otp_secret = 8;
|
||||
}
|
||||
136
services/credentials/repositories/grpc_client.go
Normal file
136
services/credentials/repositories/grpc_client.go
Normal file
|
|
@ -0,0 +1,136 @@
|
|||
package repositories
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/credentials"
|
||||
|
||||
"github.com/mitchell/selfpass/services/credentials/endpoints"
|
||||
"github.com/mitchell/selfpass/services/credentials/protobuf"
|
||||
"github.com/mitchell/selfpass/services/credentials/transport"
|
||||
"github.com/mitchell/selfpass/services/credentials/types"
|
||||
)
|
||||
|
||||
func NewCredentialServiceClient(ctx context.Context, target, ca, cert, key string) (types.CredentialClient, error) {
|
||||
keypair, err := tls.X509KeyPair([]byte(cert), []byte(key))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
capool := x509.NewCertPool()
|
||||
capool.AppendCertsFromPEM([]byte(ca))
|
||||
|
||||
creds := credentials.NewTLS(&tls.Config{
|
||||
RootCAs: capool,
|
||||
Certificates: []tls.Certificate{keypair},
|
||||
MinVersion: tls.VersionTLS12,
|
||||
CurvePreferences: []tls.CurveID{
|
||||
tls.CurveP256,
|
||||
},
|
||||
})
|
||||
|
||||
conn, err := grpc.DialContext(ctx, target, grpc.WithTransportCredentials(creds), grpc.WithBlock())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return credentialServiceClient{
|
||||
client: protobuf.NewCredentialServiceClient(conn),
|
||||
}, nil
|
||||
}
|
||||
|
||||
type credentialServiceClient struct {
|
||||
client protobuf.CredentialServiceClient
|
||||
}
|
||||
|
||||
func (c credentialServiceClient) GetAllMetadata(ctx context.Context, sourceHost string) (output <-chan types.Metadata, errch chan error) {
|
||||
pbmdch := make(chan protobuf.Metadata, 1)
|
||||
errch = make(chan error, 1)
|
||||
|
||||
stream, err := transport.DecodeMetdataStreamResponse(ctx, transport.ProtobufMetadataStream{
|
||||
Metadata: pbmdch,
|
||||
Errors: errch,
|
||||
})
|
||||
|
||||
srv, err := c.client.GetAllMetadata(ctx, &protobuf.GetAllMetadataRequest{SourceHost: sourceHost})
|
||||
if err != nil {
|
||||
errch <- err
|
||||
return nil, errch
|
||||
}
|
||||
|
||||
go func() {
|
||||
defer close(pbmdch)
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
errch <- fmt.Errorf("context timeout")
|
||||
return
|
||||
default:
|
||||
}
|
||||
|
||||
pbmd, err := srv.Recv()
|
||||
if err == io.EOF {
|
||||
return
|
||||
} else if err != nil {
|
||||
errch <- err
|
||||
return
|
||||
}
|
||||
|
||||
pbmdch <- *pbmd
|
||||
}
|
||||
}()
|
||||
|
||||
return stream.Metadata, stream.Errors
|
||||
}
|
||||
|
||||
func (c credentialServiceClient) Get(ctx context.Context, id string) (output types.Credential, err error) {
|
||||
req := transport.EncodeIdRequest(endpoints.IDRequest{ID: id})
|
||||
|
||||
res, err := c.client.Get(ctx, &req)
|
||||
if err != nil {
|
||||
return output, err
|
||||
}
|
||||
|
||||
return transport.DecodeCredential(*res)
|
||||
}
|
||||
|
||||
func (c credentialServiceClient) Create(ctx context.Context, ci types.CredentialInput) (output types.Credential, err error) {
|
||||
req := transport.EncodeCredentialRequest(ci)
|
||||
|
||||
res, err := c.client.Create(ctx, &req)
|
||||
if err != nil {
|
||||
return output, err
|
||||
}
|
||||
|
||||
return transport.DecodeCredential(*res)
|
||||
}
|
||||
|
||||
func (c credentialServiceClient) Update(ctx context.Context, id string, ci types.CredentialInput) (output types.Credential, err error) {
|
||||
req := transport.EncodeUpdateRequest(endpoints.UpdateRequest{ID: id, Credential: ci})
|
||||
|
||||
res, err := c.client.Update(ctx, &req)
|
||||
if err != nil {
|
||||
return output, err
|
||||
}
|
||||
|
||||
return transport.DecodeCredential(*res)
|
||||
}
|
||||
|
||||
func (c credentialServiceClient) Delete(ctx context.Context, id string) (err error) {
|
||||
req := transport.EncodeIdRequest(endpoints.IDRequest{ID: id})
|
||||
|
||||
res, err := c.client.Delete(ctx, &req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !res.Success {
|
||||
return fmt.Errorf("delete unsuccessful")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
81
services/credentials/repositories/redis.go
Normal file
81
services/credentials/repositories/redis.go
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
package repositories
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/mediocregopher/radix/v3"
|
||||
"github.com/mitchell/selfpass/services/credentials/types"
|
||||
)
|
||||
|
||||
func NewRedisConn(networkType, address string, connCount uint, options ...radix.PoolOpt) (c RedisConn, err error) {
|
||||
p, err := radix.NewPool(networkType, address, int(connCount), options...)
|
||||
return RedisConn{p: p}, err
|
||||
}
|
||||
|
||||
type RedisConn struct {
|
||||
p *radix.Pool
|
||||
}
|
||||
|
||||
func (conn RedisConn) GetAllMetadata(ctx context.Context, sourceHost string, errch chan<- error) (output <-chan types.Metadata) {
|
||||
mdch := make(chan types.Metadata, 1)
|
||||
|
||||
go func() {
|
||||
defer close(mdch)
|
||||
|
||||
var key string
|
||||
scr := radix.NewScanner(conn.p, radix.ScanOpts{Command: scan, Pattern: types.TypePrefixCred + dash + sourceHost + star})
|
||||
|
||||
for scr.Next(&key) {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return
|
||||
default:
|
||||
}
|
||||
|
||||
var md types.Metadata
|
||||
|
||||
if err := conn.p.Do(radix.Cmd(&md, hGetAll, key)); err != nil {
|
||||
errch <- err
|
||||
return
|
||||
}
|
||||
|
||||
mdch <- md
|
||||
}
|
||||
}()
|
||||
|
||||
return mdch
|
||||
}
|
||||
|
||||
func (conn RedisConn) Get(ctx context.Context, id string) (output types.Credential, err error) {
|
||||
err = conn.p.Do(radix.Cmd(&output, hGetAll, id))
|
||||
return output, err
|
||||
}
|
||||
|
||||
func (conn RedisConn) Put(ctx context.Context, c types.Credential) (err error) {
|
||||
err = conn.p.Do(radix.FlatCmd(nil, hMSet, c.ID, c))
|
||||
return err
|
||||
}
|
||||
|
||||
func (conn RedisConn) Delete(ctx context.Context, id string) (err error) {
|
||||
err = conn.p.Do(radix.Cmd(nil, del, id))
|
||||
return err
|
||||
}
|
||||
|
||||
func (conn RedisConn) DumpDB(ctx context.Context) (bs []byte, err error) {
|
||||
bs = []byte{}
|
||||
|
||||
if err := conn.p.Do(radix.Cmd(&bs, "DUMP")); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return bs, nil
|
||||
}
|
||||
|
||||
const (
|
||||
dash = "-"
|
||||
star = "*"
|
||||
scan = "SCAN"
|
||||
hGetAll = "HGETALL"
|
||||
hMSet = "HMSET"
|
||||
del = "DEL"
|
||||
)
|
||||
118
services/credentials/service/service.go
Normal file
118
services/credentials/service/service.go
Normal file
|
|
@ -0,0 +1,118 @@
|
|||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/mitchell/selfpass/services/credentials/types"
|
||||
)
|
||||
|
||||
func NewCredentials(repo types.CredentialRepo) Credentials {
|
||||
return Credentials{
|
||||
repo: repo,
|
||||
}
|
||||
}
|
||||
|
||||
type Credentials struct {
|
||||
repo types.CredentialRepo
|
||||
}
|
||||
|
||||
func (svc Credentials) GetAllMetadata(ctx context.Context, sourceHost string) (output <-chan types.Metadata, errch chan error) {
|
||||
errch = make(chan error, 1)
|
||||
output = svc.repo.GetAllMetadata(ctx, sourceHost, errch)
|
||||
return output, errch
|
||||
}
|
||||
|
||||
func (svc Credentials) Get(ctx context.Context, id string) (output types.Credential, err error) {
|
||||
if id == "" {
|
||||
return output, fmt.Errorf("%s must specify an id", types.InvalidArgument)
|
||||
}
|
||||
return svc.repo.Get(ctx, id)
|
||||
}
|
||||
|
||||
func (svc Credentials) Create(ctx context.Context, ci types.CredentialInput) (output types.Credential, err error) {
|
||||
if err = validateCredentialInput(ci); err != nil {
|
||||
return output, err
|
||||
}
|
||||
|
||||
var c types.Credential
|
||||
c.ID = generateID(ci)
|
||||
c.CreatedAt = time.Now()
|
||||
c.UpdatedAt = time.Now()
|
||||
c.Primary = ci.Primary
|
||||
c.LoginURL = ci.LoginURL
|
||||
c.SourceHost = ci.SourceHost
|
||||
c.Username = ci.Username
|
||||
c.Email = ci.Email
|
||||
c.Password = ci.Password
|
||||
c.OTPSecret = ci.OTPSecret
|
||||
c.Tag = ci.Tag
|
||||
|
||||
err = svc.repo.Put(ctx, c)
|
||||
|
||||
return c, err
|
||||
}
|
||||
|
||||
func validateCredentialInput(c types.CredentialInput) (err error) {
|
||||
switch {
|
||||
case c.SourceHost == "":
|
||||
return fmt.Errorf("%s must specify source host", types.InvalidArgument)
|
||||
case c.Primary == "":
|
||||
return fmt.Errorf("%s must specify primary user key", types.InvalidArgument)
|
||||
case c.Password == "":
|
||||
return fmt.Errorf("%s must specify password", types.InvalidArgument)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func generateID(ci types.CredentialInput) string {
|
||||
idFormat := types.TypePrefixCred + "-%s-%s"
|
||||
|
||||
if ci.Tag != "" {
|
||||
idFormat += "-%s"
|
||||
return fmt.Sprintf(idFormat, ci.SourceHost, ci.Primary, ci.Tag)
|
||||
}
|
||||
|
||||
return fmt.Sprintf(idFormat, ci.SourceHost, ci.Primary)
|
||||
}
|
||||
|
||||
func (svc Credentials) Update(ctx context.Context, id string, ci types.CredentialInput) (output types.Credential, err error) {
|
||||
if err = validateCredentialInput(ci); err != nil {
|
||||
return output, err
|
||||
}
|
||||
|
||||
if id == "" {
|
||||
return output, fmt.Errorf("%s must specify an id", types.InvalidArgument)
|
||||
}
|
||||
|
||||
c, err := svc.repo.Get(ctx, id)
|
||||
if err != nil {
|
||||
return output, err
|
||||
}
|
||||
|
||||
c.ID = generateID(ci)
|
||||
c.UpdatedAt = time.Now()
|
||||
c.Primary = ci.Primary
|
||||
c.LoginURL = ci.LoginURL
|
||||
c.SourceHost = ci.SourceHost
|
||||
c.Password = ci.Password
|
||||
c.OTPSecret = ci.OTPSecret
|
||||
c.Email = ci.Email
|
||||
c.Username = ci.Username
|
||||
c.Tag = ci.Tag
|
||||
|
||||
return c, svc.repo.Put(ctx, c)
|
||||
}
|
||||
|
||||
func (svc Credentials) Delete(ctx context.Context, id string) (err error) {
|
||||
if id == "" {
|
||||
return fmt.Errorf("%s must specify an id", types.InvalidArgument)
|
||||
}
|
||||
return svc.repo.Delete(ctx, id)
|
||||
}
|
||||
|
||||
func (svc Credentials) DumpDB(ctx context.Context) (bs []byte, err error) {
|
||||
return svc.repo.DumpDB(ctx)
|
||||
}
|
||||
254
services/credentials/transport/encoding.go
Normal file
254
services/credentials/transport/encoding.go
Normal file
|
|
@ -0,0 +1,254 @@
|
|||
package transport
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/golang/protobuf/ptypes"
|
||||
|
||||
"github.com/mitchell/selfpass/services/credentials/endpoints"
|
||||
"github.com/mitchell/selfpass/services/credentials/protobuf"
|
||||
"github.com/mitchell/selfpass/services/credentials/types"
|
||||
)
|
||||
|
||||
func decodeGetAllMetadataRequest(ctx context.Context, request interface{}) (interface{}, error) {
|
||||
r := request.(protobuf.GetAllMetadataRequest)
|
||||
return endpoints.GetAllMetadataRequest{
|
||||
SourceHost: r.SourceHost,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func EncodeGetAllMetadataRequest(ctx context.Context, request interface{}) (interface{}, error) {
|
||||
r := request.(endpoints.GetAllMetadataRequest)
|
||||
return protobuf.GetAllMetadataRequest{
|
||||
SourceHost: r.SourceHost,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func encodeDumpResponse(ctx context.Context, response interface{}) (interface{}, error) {
|
||||
r := response.(endpoints.DumpResponse)
|
||||
return protobuf.DumpResponse{
|
||||
Contents: r.Contents,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func encodeMetadataStreamResponse(ctx context.Context, response interface{}) (interface{}, error) {
|
||||
r := response.(endpoints.MetadataStream)
|
||||
pbmdch := make(chan protobuf.Metadata, 1)
|
||||
|
||||
go func() {
|
||||
defer close(pbmdch)
|
||||
|
||||
for md := range r.Metadata {
|
||||
createdAt, err := ptypes.TimestampProto(md.CreatedAt)
|
||||
if err != nil {
|
||||
r.Errors <- err
|
||||
return
|
||||
}
|
||||
|
||||
updatedAt, err := ptypes.TimestampProto(md.UpdatedAt)
|
||||
if err != nil {
|
||||
r.Errors <- err
|
||||
return
|
||||
}
|
||||
|
||||
pbmdch <- protobuf.Metadata{
|
||||
Id: md.ID,
|
||||
CreatedAt: createdAt,
|
||||
UpdatedAt: updatedAt,
|
||||
SourceHost: md.SourceHost,
|
||||
Primary: md.Primary,
|
||||
LoginUrl: md.LoginURL,
|
||||
Tag: md.Tag,
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
return ProtobufMetadataStream{
|
||||
Metadata: pbmdch,
|
||||
Errors: r.Errors,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func DecodeMetdataStreamResponse(ctx context.Context, r ProtobufMetadataStream) (endpoints.MetadataStream, error) {
|
||||
mdch := make(chan types.Metadata, 1)
|
||||
errch := make(chan error, 1)
|
||||
|
||||
go func() {
|
||||
defer close(mdch)
|
||||
|
||||
for pbmd := range r.Metadata {
|
||||
createdAt, err := ptypes.Timestamp(pbmd.CreatedAt)
|
||||
if err != nil {
|
||||
errch <- err
|
||||
return
|
||||
}
|
||||
|
||||
updatedAt, err := ptypes.Timestamp(pbmd.UpdatedAt)
|
||||
if err != nil {
|
||||
errch <- err
|
||||
return
|
||||
}
|
||||
|
||||
mdch <- types.Metadata{
|
||||
ID: pbmd.Id,
|
||||
SourceHost: pbmd.SourceHost,
|
||||
CreatedAt: createdAt,
|
||||
UpdatedAt: updatedAt,
|
||||
Primary: pbmd.Primary,
|
||||
LoginURL: pbmd.LoginUrl,
|
||||
Tag: pbmd.Tag,
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
return endpoints.MetadataStream{
|
||||
Metadata: mdch,
|
||||
Errors: errch,
|
||||
}, nil
|
||||
}
|
||||
|
||||
type ProtobufMetadataStream struct {
|
||||
Metadata <-chan protobuf.Metadata
|
||||
Errors chan error
|
||||
}
|
||||
|
||||
func decodeCredentialRequest(ctx context.Context, request interface{}) (interface{}, error) {
|
||||
r := request.(protobuf.CredentialRequest)
|
||||
|
||||
return types.CredentialInput{
|
||||
MetadataInput: types.MetadataInput{
|
||||
Primary: r.Primary,
|
||||
LoginURL: r.LoginUrl,
|
||||
SourceHost: r.SourceHost,
|
||||
Tag: r.Tag,
|
||||
},
|
||||
Username: r.Username,
|
||||
Email: r.Email,
|
||||
Password: r.Password,
|
||||
OTPSecret: r.OtpSecret,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func EncodeCredentialRequest(r types.CredentialInput) protobuf.CredentialRequest {
|
||||
return protobuf.CredentialRequest{
|
||||
Primary: r.Primary,
|
||||
Username: r.Username,
|
||||
Email: r.Email,
|
||||
Password: r.Password,
|
||||
OtpSecret: r.OTPSecret,
|
||||
SourceHost: r.SourceHost,
|
||||
LoginUrl: r.LoginURL,
|
||||
Tag: r.Tag,
|
||||
}
|
||||
}
|
||||
|
||||
func encodeCredentialResponse(ctx context.Context, response interface{}) (interface{}, error) {
|
||||
r := response.(types.Credential)
|
||||
|
||||
createdAt, err := ptypes.TimestampProto(r.CreatedAt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
updatedAt, err := ptypes.TimestampProto(r.UpdatedAt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return protobuf.Credential{
|
||||
Id: r.ID,
|
||||
CreatedAt: createdAt,
|
||||
UpdatedAt: updatedAt,
|
||||
Primary: r.Primary,
|
||||
SourceHost: r.SourceHost,
|
||||
LoginUrl: r.LoginURL,
|
||||
Tag: r.Tag,
|
||||
Username: r.Username,
|
||||
Email: r.Email,
|
||||
Password: r.Password,
|
||||
OtpSecret: r.OTPSecret,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func DecodeCredential(r protobuf.Credential) (c types.Credential, err error) {
|
||||
|
||||
createdAt, err := ptypes.Timestamp(r.CreatedAt)
|
||||
if err != nil {
|
||||
return c, err
|
||||
}
|
||||
|
||||
updatedAt, err := ptypes.Timestamp(r.UpdatedAt)
|
||||
if err != nil {
|
||||
return c, err
|
||||
}
|
||||
|
||||
return types.Credential{
|
||||
Metadata: types.Metadata{
|
||||
ID: r.Id,
|
||||
SourceHost: r.SourceHost,
|
||||
CreatedAt: createdAt,
|
||||
UpdatedAt: updatedAt,
|
||||
Primary: r.Primary,
|
||||
LoginURL: r.LoginUrl,
|
||||
Tag: r.Tag,
|
||||
},
|
||||
Username: r.Username,
|
||||
Email: r.Email,
|
||||
Password: r.Password,
|
||||
OTPSecret: r.OtpSecret,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func decodeUpdateRequest(ctx context.Context, request interface{}) (interface{}, error) {
|
||||
r := request.(protobuf.UpdateRequest)
|
||||
|
||||
return endpoints.UpdateRequest{
|
||||
ID: r.Id,
|
||||
Credential: types.CredentialInput{
|
||||
MetadataInput: types.MetadataInput{
|
||||
Primary: r.Credential.Primary,
|
||||
SourceHost: r.Credential.SourceHost,
|
||||
LoginURL: r.Credential.LoginUrl,
|
||||
Tag: r.Credential.Tag,
|
||||
},
|
||||
Username: r.Credential.Username,
|
||||
Email: r.Credential.Email,
|
||||
Password: r.Credential.Password,
|
||||
OTPSecret: r.Credential.OtpSecret,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func EncodeUpdateRequest(r endpoints.UpdateRequest) protobuf.UpdateRequest {
|
||||
c := r.Credential
|
||||
return protobuf.UpdateRequest{
|
||||
Id: r.ID,
|
||||
Credential: &protobuf.CredentialRequest{
|
||||
Primary: c.Primary,
|
||||
Username: c.Username,
|
||||
Email: c.Email,
|
||||
Password: c.Password,
|
||||
OtpSecret: c.OTPSecret,
|
||||
SourceHost: c.SourceHost,
|
||||
LoginUrl: c.LoginURL,
|
||||
Tag: c.Tag,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func decodeIdRequest(ctx context.Context, request interface{}) (interface{}, error) {
|
||||
r := request.(protobuf.IdRequest)
|
||||
return endpoints.IDRequest{
|
||||
ID: r.Id,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func EncodeIdRequest(r endpoints.IDRequest) protobuf.IdRequest {
|
||||
return protobuf.IdRequest{
|
||||
Id: r.ID,
|
||||
}
|
||||
}
|
||||
|
||||
func noOp(context.Context, interface{}) (interface{}, error) {
|
||||
return nil, nil
|
||||
}
|
||||
170
services/credentials/transport/grpc_server.go
Normal file
170
services/credentials/transport/grpc_server.go
Normal file
|
|
@ -0,0 +1,170 @@
|
|||
package transport
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"github.com/go-kit/kit/log"
|
||||
"github.com/go-kit/kit/transport/grpc"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
|
||||
"github.com/mitchell/selfpass/services/credentials/endpoints"
|
||||
"github.com/mitchell/selfpass/services/credentials/protobuf"
|
||||
"github.com/mitchell/selfpass/services/credentials/types"
|
||||
)
|
||||
|
||||
func NewGRPCServer(svc types.Service, logger log.Logger) GRPCServer {
|
||||
return GRPCServer{
|
||||
getAllMetadata: grpc.NewServer(
|
||||
endpoints.MakeGetAllMetadataEndpoint(svc),
|
||||
decodeGetAllMetadataRequest,
|
||||
encodeMetadataStreamResponse,
|
||||
grpc.ServerErrorLogger(logger),
|
||||
),
|
||||
get: grpc.NewServer(
|
||||
endpoints.MakeGetEndpoint(svc),
|
||||
decodeIdRequest,
|
||||
encodeCredentialResponse,
|
||||
grpc.ServerErrorLogger(logger),
|
||||
),
|
||||
create: grpc.NewServer(
|
||||
endpoints.MakeCreateEndpoint(svc),
|
||||
decodeCredentialRequest,
|
||||
encodeCredentialResponse,
|
||||
grpc.ServerErrorLogger(logger),
|
||||
),
|
||||
update: grpc.NewServer(
|
||||
endpoints.MakeUpdateEndpoint(svc),
|
||||
decodeUpdateRequest,
|
||||
encodeCredentialResponse,
|
||||
grpc.ServerErrorLogger(logger),
|
||||
),
|
||||
delete: grpc.NewServer(
|
||||
endpoints.MakeDeleteEndpoint(svc),
|
||||
decodeIdRequest,
|
||||
noOp,
|
||||
grpc.ServerErrorLogger(logger),
|
||||
),
|
||||
dump: grpc.NewServer(
|
||||
endpoints.MakeDumpEndpoint(svc),
|
||||
noOp,
|
||||
encodeDumpResponse,
|
||||
grpc.ServerErrorLogger(logger),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
type GRPCServer struct {
|
||||
getAllMetadata *grpc.Server
|
||||
get *grpc.Server
|
||||
create *grpc.Server
|
||||
update *grpc.Server
|
||||
delete *grpc.Server
|
||||
dump *grpc.Server
|
||||
}
|
||||
|
||||
func (s GRPCServer) GetAllMetadata(r *protobuf.GetAllMetadataRequest, srv protobuf.CredentialService_GetAllMetadataServer) (err error) {
|
||||
defer func() { err = handlerGRPCError(err) }()
|
||||
|
||||
var i interface{}
|
||||
ctx := srv.Context()
|
||||
|
||||
ctx, i, err = s.getAllMetadata.ServeGRPC(ctx, *r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
mds := i.(ProtobufMetadataStream)
|
||||
|
||||
receiveLoop:
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
break receiveLoop
|
||||
case err = <-mds.Errors:
|
||||
break receiveLoop
|
||||
case md, ok := <-mds.Metadata:
|
||||
if !ok {
|
||||
break receiveLoop
|
||||
}
|
||||
if err = srv.Send(&md); err != nil {
|
||||
break receiveLoop
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (s GRPCServer) Get(ctx context.Context, r *protobuf.IdRequest) (*protobuf.Credential, error) {
|
||||
ctx, i, err := s.get.ServeGRPC(ctx, *r)
|
||||
if err != nil {
|
||||
err = handlerGRPCError(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
c := &protobuf.Credential{}
|
||||
*c = i.(protobuf.Credential)
|
||||
return c, nil
|
||||
}
|
||||
|
||||
func (s GRPCServer) Create(ctx context.Context, r *protobuf.CredentialRequest) (*protobuf.Credential, error) {
|
||||
ctx, i, err := s.create.ServeGRPC(ctx, *r)
|
||||
if err != nil {
|
||||
err = handlerGRPCError(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
c := &protobuf.Credential{}
|
||||
*c = i.(protobuf.Credential)
|
||||
return c, nil
|
||||
}
|
||||
|
||||
func (s GRPCServer) Update(ctx context.Context, r *protobuf.UpdateRequest) (*protobuf.Credential, error) {
|
||||
ctx, i, err := s.update.ServeGRPC(ctx, *r)
|
||||
if err != nil {
|
||||
err = handlerGRPCError(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
c := &protobuf.Credential{}
|
||||
*c = i.(protobuf.Credential)
|
||||
return c, nil
|
||||
}
|
||||
|
||||
func (s GRPCServer) Delete(ctx context.Context, r *protobuf.IdRequest) (*protobuf.DeleteResponse, error) {
|
||||
ctx, _, err := s.delete.ServeGRPC(ctx, *r)
|
||||
if err != nil {
|
||||
err = handlerGRPCError(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &protobuf.DeleteResponse{Success: true}, nil
|
||||
}
|
||||
|
||||
func (s GRPCServer) Dump(ctx context.Context, r *protobuf.EmptyRequest) (*protobuf.DumpResponse, error) {
|
||||
ctx, i, err := s.dump.ServeGRPC(ctx, *r)
|
||||
if err != nil {
|
||||
err = handlerGRPCError(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
res := &protobuf.DumpResponse{}
|
||||
*res = i.(protobuf.DumpResponse)
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func handlerGRPCError(err error) error {
|
||||
if err != nil {
|
||||
switch {
|
||||
case strings.HasPrefix(err.Error(), types.InvalidArgument):
|
||||
err = status.Error(codes.InvalidArgument, err.Error())
|
||||
case strings.HasPrefix(err.Error(), types.NotFound):
|
||||
err = status.Error(codes.NotFound, err.Error())
|
||||
default:
|
||||
err = status.Error(codes.Internal, "an internal error has occurred")
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
75
services/credentials/types/credential.go
Normal file
75
services/credentials/types/credential.go
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
package types
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
const TypePrefixCred = "cred"
|
||||
|
||||
type Credential struct {
|
||||
Metadata
|
||||
Username string
|
||||
Email string
|
||||
Password string `json:"-"`
|
||||
OTPSecret string `json:"-"`
|
||||
}
|
||||
|
||||
func (c Credential) String() string {
|
||||
format := "%s"
|
||||
args := []interface{}{c.Metadata}
|
||||
|
||||
if c.Username != "" {
|
||||
format += "username = %s\n"
|
||||
args = append(args, c.Username)
|
||||
}
|
||||
|
||||
if c.Email != "" {
|
||||
format += "email = %s\n"
|
||||
args = append(args, c.Email)
|
||||
}
|
||||
|
||||
return fmt.Sprintf(format, args...)
|
||||
}
|
||||
|
||||
type CredentialInput struct {
|
||||
MetadataInput
|
||||
Username string
|
||||
Email string
|
||||
Password string
|
||||
OTPSecret string
|
||||
}
|
||||
|
||||
type Metadata struct {
|
||||
ID string // primary key
|
||||
SourceHost string // sort key
|
||||
CreatedAt time.Time
|
||||
UpdatedAt time.Time
|
||||
Primary string
|
||||
LoginURL string
|
||||
Tag string
|
||||
}
|
||||
|
||||
func (m Metadata) String() string {
|
||||
format := "id = %s\ncreatedAt = %s\nupdatedAt = %s\nsourceHost = %s\nprimary = %s\n"
|
||||
args := []interface{}{m.ID, m.CreatedAt, m.UpdatedAt, m.SourceHost, m.Primary}
|
||||
|
||||
if m.LoginURL != "" {
|
||||
format += "loginUrl = %s\n"
|
||||
args = append(args, m.LoginURL)
|
||||
}
|
||||
|
||||
if m.Tag != "" {
|
||||
format += "tag = %s\n"
|
||||
args = append(args, m.Tag)
|
||||
}
|
||||
|
||||
return fmt.Sprintf(format, args...)
|
||||
}
|
||||
|
||||
type MetadataInput struct {
|
||||
Primary string
|
||||
SourceHost string
|
||||
LoginURL string
|
||||
Tag string
|
||||
}
|
||||
8
services/credentials/types/error_prefixes.go
Normal file
8
services/credentials/types/error_prefixes.go
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
package types
|
||||
|
||||
// These constants are the prefixes of errors that should be exposed to the client.
|
||||
// All error encoders should check for them.
|
||||
const (
|
||||
NotFound = "not found:"
|
||||
InvalidArgument = "invalid argument:"
|
||||
)
|
||||
30
services/credentials/types/interfaces.go
Normal file
30
services/credentials/types/interfaces.go
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
package types
|
||||
|
||||
import "context"
|
||||
|
||||
type Service interface {
|
||||
GetAllMetadata(ctx context.Context, sourceHost string) (output <-chan Metadata, errch chan error)
|
||||
Get(ctx context.Context, id string) (output Credential, err error)
|
||||
Create(ctx context.Context, ci CredentialInput) (output Credential, err error)
|
||||
Update(ctx context.Context, id string, ci CredentialInput) (output Credential, err error)
|
||||
Delete(ctx context.Context, id string) (err error)
|
||||
DumpDB(ctx context.Context) (bs []byte, err error)
|
||||
}
|
||||
|
||||
type CredentialRepo interface {
|
||||
GetAllMetadata(ctx context.Context, sourceHost string, errch chan<- error) (output <-chan Metadata)
|
||||
Get(ctx context.Context, id string) (output Credential, err error)
|
||||
Put(ctx context.Context, c Credential) (err error)
|
||||
Delete(ctx context.Context, id string) (err error)
|
||||
DumpDB(ctx context.Context) (bs []byte, err error)
|
||||
}
|
||||
|
||||
type CredentialClientInit func(ctx context.Context, target, ca, cert, key string) (c CredentialClient, err error)
|
||||
|
||||
type CredentialClient interface {
|
||||
GetAllMetadata(ctx context.Context, sourceHost string) (output <-chan Metadata, errch chan error)
|
||||
Get(ctx context.Context, id string) (output Credential, err error)
|
||||
Create(ctx context.Context, ci CredentialInput) (output Credential, err error)
|
||||
Update(ctx context.Context, id string, ci CredentialInput) (output Credential, err error)
|
||||
Delete(ctx context.Context, id string) (err error)
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue