summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShulhan <ms@kilabit.info>2023-07-24 13:01:36 +0700
committerShulhan <ms@kilabit.info>2023-10-06 10:03:04 +0700
commit8a1a81a6428ae970569d9c2a506acf90deb2e0c4 (patch)
treed3e82e19718962181b51572a0395ed6b1cef2222
parent479e33040d93e582aa10f19c299b2633f2270d24 (diff)
downloadgotp-8a1a81a6428ae970569d9c2a506acf90deb2e0c4.tar.xz
all: unfold private key path before reading
By unfolding, user can set the path to private key using "~" that points to their home. This make the key can works across home directory, in case user have multiple homes (Linux and macOS have different home path and maybe user name, but both can use "~" as substitution for $HOME)
-rw-r--r--cli_test.go9
-rw-r--r--config.go42
-rw-r--r--config_test.go40
-rw-r--r--go.mod10
-rw-r--r--go.sum17
-rw-r--r--testdata/config_marshaler_test.txt17
6 files changed, 105 insertions, 30 deletions
diff --git a/cli_test.go b/cli_test.go
index 81253b1..5eeffd4 100644
--- a/cli_test.go
+++ b/cli_test.go
@@ -151,14 +151,15 @@ func TestCli_SetPrivateKey(t *testing.T) {
}
var (
- cli = &Cli{}
+ cli = &Cli{}
+ cfg = &config{}
+
rawConfig []byte
- cfg *config
)
rawConfig = tdata.Input[`config.ini`]
- cfg, err = loadConfig(rawConfig)
+ err = cfg.UnmarshalText(rawConfig)
if err != nil {
t.Fatal(err)
}
@@ -185,7 +186,7 @@ func TestCli_SetPrivateKey(t *testing.T) {
// Load the encrypted raw config and compare the issuer.
- cfg, err = loadConfig(rawConfig)
+ err = cfg.UnmarshalText(rawConfig)
if err != nil {
t.Fatal(err)
}
diff --git a/config.go b/config.go
index 024450c..c7150d6 100644
--- a/config.go
+++ b/config.go
@@ -13,6 +13,7 @@ import (
"strings"
"github.com/shuLhan/share/lib/ini"
+ libos "github.com/shuLhan/share/lib/os"
)
const (
@@ -42,18 +43,18 @@ func newConfig(file string) (cfg *config, err error) {
if !errors.Is(err, fs.ErrNotExist) {
return nil, fmt.Errorf(`%s: Open %q: %w`, logp, file, err)
}
- isNotExist = true
- }
- if isNotExist {
var dir = filepath.Dir(file)
err = os.MkdirAll(dir, 0700)
if err != nil {
return nil, fmt.Errorf(`%s: MkdirAll %q: %w`, logp, dir, err)
}
+ isNotExist = true
}
- cfg, err = loadConfig(content)
+ cfg = &config{}
+
+ err = cfg.UnmarshalText(content)
if err != nil {
return nil, fmt.Errorf(`%s: %w`, logp, err)
}
@@ -64,25 +65,40 @@ func newConfig(file string) (cfg *config, err error) {
return cfg, nil
}
-// loadConfig load configuration from raw bytes.
-func loadConfig(content []byte) (cfg *config, err error) {
- var logp = `loadConfig`
+// UnmarshalText load configuration from raw bytes.
+func (cfg *config) UnmarshalText(content []byte) (err error) {
+ var logp = `UnmarshalText`
+
+ cfg.Issuers = make(map[string]string)
- cfg = &config{
- Issuers: make(map[string]string),
+ if len(content) > 0 {
+ err = ini.Unmarshal(content, cfg)
+ if err != nil {
+ return fmt.Errorf(`%s: %w`, logp, err)
+ }
}
- err = ini.Unmarshal(content, cfg)
- if err != nil {
- return nil, fmt.Errorf(`%s: %w`, logp, err)
+ if len(cfg.PrivateKey) != 0 {
+ cfg.PrivateKey, err = libos.PathUnfold(cfg.PrivateKey)
+ if err != nil {
+ return fmt.Errorf(`%s: %w`, logp, err)
+ }
}
- return cfg, nil
+ return nil
}
// MarshalText convert the config object back to INI format.
func (cfg *config) MarshalText() (text []byte, err error) {
var logp = `MarshalText`
+
+ if len(cfg.PrivateKey) != 0 {
+ cfg.PrivateKey, err = libos.PathFold(cfg.PrivateKey)
+ if err != nil {
+ return nil, fmt.Errorf(`%s: %w`, logp, err)
+ }
+ }
+
text, err = ini.Marshal(cfg)
if err != nil {
return nil, fmt.Errorf(`%s: %w`, logp, err)
diff --git a/config_test.go b/config_test.go
index b877236..477b438 100644
--- a/config_test.go
+++ b/config_test.go
@@ -4,6 +4,8 @@
package gotp
import (
+ "os"
+ "path/filepath"
"testing"
"github.com/shuLhan/share/lib/test"
@@ -57,3 +59,41 @@ func TestNewConfig(t *testing.T) {
test.Assert(t, `Issuer`, c.expConfig, gotConfig)
}
}
+
+func TestMarshaler(t *testing.T) {
+ var (
+ cfg = config{}
+
+ tdata *test.Data
+ userHomeDir string
+ err error
+ )
+
+ tdata, err = test.LoadData(`testdata/config_marshaler_test.txt`)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ err = cfg.UnmarshalText(tdata.Input[`input.ini`])
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ userHomeDir, err = os.UserHomeDir()
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ var expPrivateKey = filepath.Join(userHomeDir, `myprivatekey.pem`)
+
+ test.Assert(t, `UnmarshalText: PrivateKey`, expPrivateKey, cfg.PrivateKey)
+
+ var gotText []byte
+
+ gotText, err = cfg.MarshalText()
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ test.Assert(t, `MarshalText`, string(tdata.Output[`output.ini`]), string(gotText))
+}
diff --git a/go.mod b/go.mod
index 39f2ec5..b58dbdf 100644
--- a/go.mod
+++ b/go.mod
@@ -3,14 +3,14 @@
module git.sr.ht/~shulhan/gotp
-go 1.19
+go 1.20
require (
- github.com/shuLhan/share v0.46.0
- golang.org/x/crypto v0.9.0
- golang.org/x/term v0.8.0
+ github.com/shuLhan/share v0.50.0
+ golang.org/x/crypto v0.13.0
+ golang.org/x/term v0.12.0
)
-require golang.org/x/sys v0.8.0 // indirect
+require golang.org/x/sys v0.12.0 // indirect
//replace github.com/shuLhan/share => ../share
diff --git a/go.sum b/go.sum
index 922af09..5680417 100644
--- a/go.sum
+++ b/go.sum
@@ -1,8 +1,9 @@
-github.com/shuLhan/share v0.46.0 h1:cF0Ngj7wVA6TIcdSmfrqxOwMB3hZ+4df5cJf4GGCun4=
-github.com/shuLhan/share v0.46.0/go.mod h1:BhnIWJxq84BTOs3Z2gLFAN8ih9mBfhZbRIjqGupGJag=
-golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g=
-golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0=
-golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
-golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/term v0.8.0 h1:n5xxQn2i3PC0yLAbjTpNT85q/Kgzcr2gIoX9OrJUols=
-golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
+github.com/shuLhan/share v0.50.0 h1:L1TR7jsSOv5cDMkH4CapIzDp/Yisq5Xe16GMeQRCSMs=
+github.com/shuLhan/share v0.50.0/go.mod h1:YEwLUwwBpDqPn5yxfdb0B8eFP04SKQxv5gMQwB4A+c4=
+golang.org/x/crypto v0.13.0 h1:mvySKfSWJ+UKUii46M40LOvyWfN0s2U+46/jDd0e6Ck=
+golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
+golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8=
+golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o=
+golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/term v0.12.0 h1:/ZfYdc3zq+q02Rv9vGqTeSItdzZTSNDmfTi0mBAuidU=
+golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
diff --git a/testdata/config_marshaler_test.txt b/testdata/config_marshaler_test.txt
new file mode 100644
index 0000000..b354b28
--- /dev/null
+++ b/testdata/config_marshaler_test.txt
@@ -0,0 +1,17 @@
+Test UnmarshalText and MarshalText on config.
+
+>>> input.ini
+[gotp "issuer"]
+test1 = SHA1:a:6:30:
+test2 = SHA1:b:6:30:
+
+[gotp]
+private_key = ~/myprivatekey.pem
+
+<<< output.ini
+[gotp "issuer"]
+test1 = SHA1:a:6:30:
+test2 = SHA1:b:6:30:
+
+[gotp]
+private_key = ~/myprivatekey.pem