mirror of
https://git.mills.io/saltyim/saltyim.git
synced 2024-06-16 11:58:24 +00:00
refactor identity create/read for functional arguments to support PWA (#53)
This PR is for refactoring interaction with CreateIdentity(), GetIdentity(), and NewClient() to allow operations on the identity contents from within a PWA where a filesystem is not present. It was suggested to use functional arguments so this pull request reflects this. Co-authored-by: mlctrez <mlctrez@gmail.com> Reviewed-on: https://git.mills.io/saltyim/saltyim/pulls/53 Co-authored-by: mlctrez <mlctrez@noreply@mills.io> Co-committed-by: mlctrez <mlctrez@noreply@mills.io>
This commit is contained in:
parent
332202551d
commit
05c44be6c0
16
client.go
16
client.go
@ -45,33 +45,33 @@ type Client struct {
|
||||
cache configCache
|
||||
}
|
||||
|
||||
// NewClient reeturns a new Salty IM client for sending and receiving
|
||||
// NewClient returns a new Salty IM client for sending and receiving
|
||||
// encrypted messages to other Salty IM users as well as decrypting
|
||||
// and displaying messages of the user's own inbox.
|
||||
func NewClient(me *Addr, identity string) (*Client, error) {
|
||||
key, m, err := GetIdentity(identity)
|
||||
func NewClient(me *Addr, options ...IdentityOption) (*Client, error) {
|
||||
ident, err := GetIdentity(options...)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error opening identity %s: %w", identity, err)
|
||||
return nil, fmt.Errorf("error opening identity %s: %w", ident.Source(), err)
|
||||
}
|
||||
if me == nil || me.IsZero() {
|
||||
me = m
|
||||
me = ident.addr
|
||||
}
|
||||
|
||||
if me == nil || me.IsZero() {
|
||||
return nil, fmt.Errorf("unable to find your user addressn in %s", identity)
|
||||
return nil, fmt.Errorf("unable to find your user addressn in %s", ident.Source())
|
||||
}
|
||||
|
||||
if err := me.Refresh(); err != nil {
|
||||
return nil, fmt.Errorf("error looking up user endpoint: %w", err)
|
||||
}
|
||||
|
||||
log.Debugf("Using identity %s with public key %s", identity, key)
|
||||
log.Debugf("Using identity %s with public key %s", ident.Source(), ident.key)
|
||||
log.Debugf("Salty Addr is %s", me)
|
||||
log.Debugf("Endpoint is %s", me.Endpoint())
|
||||
|
||||
return &Client{
|
||||
me: me,
|
||||
key: key,
|
||||
key: ident.key,
|
||||
cache: make(configCache),
|
||||
}, nil
|
||||
}
|
||||
|
@ -47,7 +47,7 @@ func init() {
|
||||
}
|
||||
|
||||
func chat(me *saltyim.Addr, identity, user string) {
|
||||
cli, err := saltyim.NewClient(me, identity)
|
||||
cli, err := saltyim.NewClient(me, saltyim.IdentityPath(identity))
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "error initializing client: %s\n", err)
|
||||
os.Exit(2)
|
||||
|
@ -107,12 +107,12 @@ func makeuser(me *saltyim.Addr, identity, endpoint string) {
|
||||
os.Exit(2)
|
||||
}
|
||||
|
||||
if err := saltyim.CreateIdentity(identity, me.String()); err != nil {
|
||||
if _, err := saltyim.CreateIdentity(saltyim.IdentityPath(identity), saltyim.IdentityAddr(me)); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "error creating identity %q for %s: %s\n", identity, me, err)
|
||||
os.Exit(2)
|
||||
}
|
||||
|
||||
key, _, err := saltyim.GetIdentity(identity)
|
||||
ident, err := saltyim.GetIdentity(saltyim.IdentityPath(identity))
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "error reading identity %s for %s: %s\n", identity, me, err)
|
||||
os.Exit(2)
|
||||
@ -121,7 +121,7 @@ func makeuser(me *saltyim.Addr, identity, endpoint string) {
|
||||
ctx := setupCtx{
|
||||
Config: saltyim.Config{
|
||||
Endpoint: u.String(),
|
||||
Key: key.PublicKey().ID().String(),
|
||||
Key: ident.Key().PublicKey().ID().String(),
|
||||
},
|
||||
Addr: me,
|
||||
}
|
||||
|
@ -74,7 +74,7 @@ func init() {
|
||||
}
|
||||
|
||||
func read(me *saltyim.Addr, identity string, prehook, posthook string, args ...string) {
|
||||
cli, err := saltyim.NewClient(me, identity)
|
||||
cli, err := saltyim.NewClient(me, saltyim.IdentityPath(identity))
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "error initializing client: %s\n", err)
|
||||
os.Exit(2)
|
||||
|
@ -50,7 +50,7 @@ func init() {
|
||||
}
|
||||
|
||||
func register(me *saltyim.Addr, identity string) {
|
||||
cli, err := saltyim.NewClient(me, identity)
|
||||
cli, err := saltyim.NewClient(me, saltyim.IdentityPath(identity))
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "error initializing client: %s\n", err)
|
||||
os.Exit(2)
|
||||
|
@ -67,7 +67,7 @@ func send(me *saltyim.Addr, identity, user string, args ...string) {
|
||||
os.Exit(2)
|
||||
}
|
||||
|
||||
cli, err := saltyim.NewClient(me, identity)
|
||||
cli, err := saltyim.NewClient(me, saltyim.IdentityPath(identity))
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "error initializing client: %s\n", err)
|
||||
os.Exit(2)
|
||||
|
137
identity.go
137
identity.go
@ -2,8 +2,10 @@ package saltyim
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
@ -42,48 +44,137 @@ func DefaultEndpoint() string {
|
||||
}
|
||||
|
||||
// CreateIdentity ...
|
||||
func CreateIdentity(fn, user string) error {
|
||||
func CreateIdentity(options ...IdentityOption) (*Identity, error) {
|
||||
|
||||
ident := &Identity{}
|
||||
for _, option := range options {
|
||||
option(ident)
|
||||
}
|
||||
|
||||
if ident.addr == nil || ident.addr.IsZero() {
|
||||
return nil, fmt.Errorf("unable to find user address in options")
|
||||
}
|
||||
|
||||
buf := &bytes.Buffer{}
|
||||
|
||||
salty.GenerateKeys(buf)
|
||||
|
||||
buf.Write([]byte(fmt.Sprintf("# user: %s\n", ident.addr.String())))
|
||||
|
||||
ident.contents = buf.Bytes()
|
||||
|
||||
if ident.path == "" {
|
||||
return ident, nil
|
||||
}
|
||||
|
||||
fn := ident.path
|
||||
|
||||
f, err := os.OpenFile(fn, os.O_CREATE|os.O_EXCL|os.O_WRONLY, 0600)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error opening identity %q for writing: %w", fn, err)
|
||||
return ident, fmt.Errorf("error opening identity %q for writing: %w", fn, err)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
salty.GenerateKeys(f)
|
||||
|
||||
f.Write([]byte(fmt.Sprintf("# user: %s\n", user)))
|
||||
if _, err := f.Write(ident.contents); err != nil {
|
||||
return ident, fmt.Errorf("error writing identity %q: %w", fn, err)
|
||||
}
|
||||
|
||||
if err := f.Sync(); err != nil {
|
||||
return fmt.Errorf("error syncing identity %q for writing: %w", fn, err)
|
||||
return ident, fmt.Errorf("error syncing identity %q for writing: %w", fn, err)
|
||||
}
|
||||
|
||||
if err := f.Close(); err != nil {
|
||||
return fmt.Errorf("error closing identity %q for writing: %w", fn, err)
|
||||
return ident, fmt.Errorf("error closing identity %q for writing: %w", fn, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
return ident, nil
|
||||
}
|
||||
|
||||
// GetIdentity ...
|
||||
func GetIdentity(fn string) (*keys.EdX25519Key, *Addr, error) {
|
||||
// Handle unix home with `~`
|
||||
if strings.HasPrefix(fn, "~/") {
|
||||
dirname, _ := os.UserHomeDir()
|
||||
fn = filepath.Join(dirname, fn[2:])
|
||||
func GetIdentity(options ...IdentityOption) (*Identity, error) {
|
||||
|
||||
ident := &Identity{}
|
||||
for _, option := range options {
|
||||
option(ident)
|
||||
}
|
||||
|
||||
id, err := os.Open(fn)
|
||||
if ident.path != "" {
|
||||
fn := ident.path
|
||||
// Handle unix home with `~`
|
||||
if strings.HasPrefix(fn, "~/") {
|
||||
dirname, _ := os.UserHomeDir()
|
||||
fn = filepath.Join(dirname, fn[2:])
|
||||
}
|
||||
|
||||
id, err := os.Open(fn)
|
||||
if err != nil {
|
||||
return ident, fmt.Errorf("error opening identity %q: %s", ident.Source(), err)
|
||||
}
|
||||
defer id.Close()
|
||||
identityBytes, err := ioutil.ReadAll(id)
|
||||
if err != nil {
|
||||
return ident, fmt.Errorf("error opening identity %q: %s", ident.Source(), err)
|
||||
}
|
||||
ident.contents = identityBytes
|
||||
}
|
||||
|
||||
key, err := salty.ParseIdentity(bytes.NewBuffer(ident.contents))
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("error opening identity %q: %s", fn, err)
|
||||
return ident, fmt.Errorf("error reading identity %q: %s", ident.Source(), err)
|
||||
}
|
||||
defer id.Close()
|
||||
ident.key = key
|
||||
|
||||
key, err := salty.ParseIdentity(id)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("error reading identity %q: %s", fn, err)
|
||||
}
|
||||
me, err := readUser(bytes.NewBuffer(ident.contents))
|
||||
ident.addr = me
|
||||
|
||||
id.Seek(0, 0)
|
||||
me, err := readUser(id)
|
||||
return key, me, err
|
||||
return ident, err
|
||||
}
|
||||
|
||||
// Identity allows interaction with CreateIdentity, GetIdentity, and NewClient
|
||||
type Identity struct {
|
||||
// path where identity is read or written to
|
||||
path string
|
||||
// contents where identity is read from or stored
|
||||
contents []byte
|
||||
// key is the identity key
|
||||
key *keys.EdX25519Key
|
||||
// addr is the user / endpoint
|
||||
addr *Addr
|
||||
}
|
||||
|
||||
func (i *Identity) Source() string {
|
||||
if i.path != "" {
|
||||
return i.path
|
||||
}
|
||||
return "[]byte"
|
||||
}
|
||||
|
||||
func (i *Identity) Contents() []byte {
|
||||
return i.contents
|
||||
}
|
||||
|
||||
func (i *Identity) Key() *keys.EdX25519Key {
|
||||
return i.key
|
||||
}
|
||||
|
||||
func (i *Identity) Addr() *Addr {
|
||||
return i.addr
|
||||
}
|
||||
|
||||
// IdentityOption represents functional options for various identity operations
|
||||
type IdentityOption func(*Identity)
|
||||
|
||||
// IdentityAddr sets the identity Addr option
|
||||
func IdentityAddr(addr *Addr) IdentityOption {
|
||||
return func(i *Identity) { i.addr = addr }
|
||||
}
|
||||
|
||||
// IdentityPath indicates that an identity should be read / written from a file path
|
||||
func IdentityPath(path string) IdentityOption {
|
||||
return func(i *Identity) { i.path = path }
|
||||
}
|
||||
|
||||
// IdentityContents indicates that the identity should be read from a byte array
|
||||
func IdentityContents(contents []byte) IdentityOption {
|
||||
return func(i *Identity) { i.contents = contents }
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user