commit 0c8a8a7be66adccfe1955eb9086d570ebf1b1762
parent d24f7fadd4ec1c907cbf8ceb741d9c82338f6506
Author: Sean Enck <sean@ttypty.com>
Date: Tue, 25 Jul 2023 20:06:26 -0400
system split to inputs, platform, other
Diffstat:
10 files changed, 59 insertions(+), 146 deletions(-)
diff --git a/internal/backend/actions.go b/internal/backend/actions.go
@@ -8,7 +8,6 @@ import (
"time"
"github.com/enckse/lockbox/internal/inputs"
- "github.com/enckse/lockbox/internal/system"
"github.com/tobischo/gokeepasslib/v3"
"github.com/tobischo/gokeepasslib/v3/wrappers"
)
@@ -22,7 +21,7 @@ func (t *Transaction) act(cb action) error {
return err
}
k := string(key)
- file := system.EnvironOrDefault(inputs.KeyFileEnv, "")
+ file := inputs.EnvironOrDefault(inputs.KeyFileEnv, "")
if !t.exists {
if err := create(t.file, k, file); err != nil {
return err
@@ -164,7 +163,7 @@ func (t *Transaction) Move(src QueryEntity, dst string) error {
if strings.TrimSpace(src.Value) == "" {
return errors.New("empty secret not allowed")
}
- mod := system.EnvironOrDefault(inputs.ModTimeEnv, "")
+ mod := inputs.EnvironOrDefault(inputs.ModTimeEnv, "")
modTime := time.Now()
if mod != "" {
p, err := time.Parse(inputs.ModTimeFormat, mod)
diff --git a/internal/backend/hooks.go b/internal/backend/hooks.go
@@ -10,7 +10,6 @@ import (
"github.com/enckse/lockbox/internal/inputs"
"github.com/enckse/lockbox/internal/platform"
- "github.com/enckse/lockbox/internal/system"
)
// NewHook will create a new hook type
@@ -18,7 +17,7 @@ func NewHook(path string, a ActionMode) (Hook, error) {
if strings.TrimSpace(path) == "" {
return Hook{}, errors.New("empty path is not allowed for hooks")
}
- dir := system.EnvironOrDefault(inputs.HookDirEnv, "")
+ dir := inputs.EnvironOrDefault(inputs.HookDirEnv, "")
if dir == "" {
return Hook{enabled: false}, nil
}
diff --git a/internal/inputs/env.go b/internal/inputs/env.go
@@ -12,11 +12,12 @@ import (
"strings"
"time"
- "github.com/enckse/lockbox/internal/system"
"mvdan.cc/sh/v3/shell"
)
const (
+ yes = "yes"
+ no = "no"
prefixKey = "LOCKBOX_"
noClipEnv = prefixKey + "NOCLIP"
noColorEnv = prefixKey + "NOCOLOR"
@@ -72,7 +73,7 @@ const (
hashJSONLengthEnv = JSONDataOutputEnv + "_HASH_LENGTH"
)
-var isYesNoArgs = []string{system.Yes, system.No}
+var isYesNoArgs = []string{yes, no}
type (
environmentOutput struct {
@@ -206,20 +207,6 @@ func getKey(keyMode, name string) ([]byte, error) {
return []byte(strings.TrimSpace(string(data))), nil
}
-func isYesNoEnv(defaultValue bool, envKey string) (bool, error) {
- read := system.EnvironValue(envKey)
- switch read {
- case system.NoValue:
- return false, nil
- case system.YesValue:
- return true, nil
- case system.EmptyValue:
- return defaultValue, nil
- }
-
- return false, fmt.Errorf("invalid yes/no env value for %s", envKey)
-}
-
// IsClipOSC52 indicates if OSC52 mode is enabled
func IsClipOSC52() (bool, error) {
return isYesNoEnv(false, clipOSC52Env)
@@ -252,7 +239,7 @@ func IsInteractive() (bool, error) {
// TOTPToken gets the name of the totp special case tokens
func TOTPToken() string {
- return system.EnvironOrDefault(fieldTOTPEnv, defaultTOTPField)
+ return EnvironOrDefault(fieldTOTPEnv, defaultTOTPField)
}
func (o environmentOutput) formatEnvironmentVariable(required bool, name, val, desc string, allowed []string) string {
@@ -284,10 +271,10 @@ func ListEnvironmentVariables(showValues bool) []string {
results = append(results, e.formatEnvironmentVariable(true, StoreEnv, "", "directory to the database file", []string{"file"}))
results = append(results, e.formatEnvironmentVariable(true, keyModeEnv, commandKeyMode, "how to retrieve the database store password", []string{commandKeyMode, plainKeyMode}))
results = append(results, e.formatEnvironmentVariable(true, keyEnv, "", fmt.Sprintf("the database key ('%s' mode) or command to run ('%s' mode)\nto retrieve the database password", plainKeyMode, commandKeyMode), []string{commandArgsExample, "password"}))
- results = append(results, e.formatEnvironmentVariable(false, noClipEnv, system.No, "disable clipboard operations", isYesNoArgs))
- results = append(results, e.formatEnvironmentVariable(false, noColorEnv, system.No, "disable terminal colors", isYesNoArgs))
- results = append(results, e.formatEnvironmentVariable(false, interactiveEnv, system.Yes, "enable interactive mode", isYesNoArgs))
- results = append(results, e.formatEnvironmentVariable(false, readOnlyEnv, system.No, "operate in readonly mode", isYesNoArgs))
+ results = append(results, e.formatEnvironmentVariable(false, noClipEnv, no, "disable clipboard operations", isYesNoArgs))
+ results = append(results, e.formatEnvironmentVariable(false, noColorEnv, no, "disable terminal colors", isYesNoArgs))
+ results = append(results, e.formatEnvironmentVariable(false, interactiveEnv, yes, "enable interactive mode", isYesNoArgs))
+ results = append(results, e.formatEnvironmentVariable(false, readOnlyEnv, no, "operate in readonly mode", isYesNoArgs))
results = append(results, e.formatEnvironmentVariable(false, fieldTOTPEnv, defaultTOTPField, "attribute name to store TOTP tokens within the database", []string{"string"}))
results = append(results, e.formatEnvironmentVariable(false, formatTOTPEnv, strings.ReplaceAll(strings.ReplaceAll(FormatTOTP("%s"), "%25s", "%s"), "&", " \\\n &"), "override the otpauth url used to store totp tokens. It must have ONE format\nstring ('%s') to insert the totp base code", []string{"otpauth//url/%s/args..."}))
results = append(results, e.formatEnvironmentVariable(false, MaxTOTPTime, MaxTOTPTimeDefault, "time, in seconds, in which to show a TOTP token before automatically exiting", []string{"integer"}))
@@ -296,12 +283,35 @@ func ListEnvironmentVariables(showValues bool) []string {
results = append(results, e.formatEnvironmentVariable(false, ClipCopyEnv, detectedValue, "override the detected platform copy command", []string{commandArgsExample}))
results = append(results, e.formatEnvironmentVariable(false, clipMaxEnv, fmt.Sprintf("%d", defaultMaxClipboard), "override the amount of time before totp clears the clipboard (e.g. 10),\nmust be an integer", []string{"integer"}))
results = append(results, e.formatEnvironmentVariable(false, PlatformEnv, detectedValue, "override the detected platform", PlatformSet()))
- results = append(results, e.formatEnvironmentVariable(false, noTOTPEnv, system.No, "disable TOTP integrations", isYesNoArgs))
+ results = append(results, e.formatEnvironmentVariable(false, noTOTPEnv, no, "disable TOTP integrations", isYesNoArgs))
results = append(results, e.formatEnvironmentVariable(false, HookDirEnv, "", "the path to hooks to execute on actions against the database", []string{"directory"}))
- results = append(results, e.formatEnvironmentVariable(false, clipOSC52Env, system.No, "enable OSC52 clipboard mode", isYesNoArgs))
+ results = append(results, e.formatEnvironmentVariable(false, clipOSC52Env, no, "enable OSC52 clipboard mode", isYesNoArgs))
results = append(results, e.formatEnvironmentVariable(false, KeyFileEnv, "", "additional keyfile to access/protect the database", []string{"keyfile"}))
results = append(results, e.formatEnvironmentVariable(false, ModTimeEnv, ModTimeFormat, fmt.Sprintf("input modification time to set for the entry\n(expected format: %s)", ModTimeFormat), []string{"modtime"}))
results = append(results, e.formatEnvironmentVariable(false, JSONDataOutputEnv, string(JSONDataOutputHash), fmt.Sprintf("changes what the data field in JSON outputs will contain\nuse '%s' with CAUTION", JSONDataOutputRaw), []string{string(JSONDataOutputRaw), string(JSONDataOutputHash), string(JSONDataOutputBlank)}))
results = append(results, e.formatEnvironmentVariable(false, hashJSONLengthEnv, fmt.Sprintf("%d", defaultHashLength), fmt.Sprintf("maximum hash length the JSON output should contain\nwhen '%s' mode is set for JSON output", JSONDataOutputHash), []string{"integer"}))
return results
}
+
+// EnvironOrDefault will get the environment value OR default if env is not set.
+func EnvironOrDefault(envKey, defaultValue string) string {
+ val := os.Getenv(envKey)
+ if strings.TrimSpace(val) == "" {
+ return defaultValue
+ }
+ return val
+}
+
+func isYesNoEnv(defaultValue bool, envKey string) (bool, error) {
+ read := strings.ToLower(strings.TrimSpace(os.Getenv(envKey)))
+ switch read {
+ case no:
+ return false, nil
+ case yes:
+ return true, nil
+ case "":
+ return defaultValue, nil
+ }
+
+ return false, fmt.Errorf("invalid yes/no env value for %s", envKey)
+}
diff --git a/internal/inputs/env_test.go b/internal/inputs/env_test.go
@@ -198,3 +198,21 @@ func TestGetHashLength(t *testing.T) {
t.Errorf("invalid err: %v", err)
}
}
+
+func TestEnvDefault(t *testing.T) {
+ os.Clearenv()
+ val := inputs.EnvironOrDefault("TEST", "value")
+ if val != "value" {
+ t.Error("invalid read")
+ }
+ os.Setenv("TEST", " ")
+ val = inputs.EnvironOrDefault("TEST", "value")
+ if val != "value" {
+ t.Error("invalid read")
+ }
+ os.Setenv("TEST", " a")
+ val = inputs.EnvironOrDefault("TEST", "value")
+ if val != " a" {
+ t.Error("invalid read")
+ }
+}
diff --git a/internal/inputs/json.go b/internal/inputs/json.go
@@ -4,8 +4,6 @@ package inputs
import (
"fmt"
"strings"
-
- "github.com/enckse/lockbox/internal/system"
)
const (
@@ -24,7 +22,7 @@ type (
// ParseJSONOutput handles detecting the JSON output mode
func ParseJSONOutput() (JSONOutputMode, error) {
- val := strings.ToLower(strings.TrimSpace(system.EnvironOrDefault(JSONDataOutputEnv, string(JSONDataOutputHash))))
+ val := strings.ToLower(strings.TrimSpace(EnvironOrDefault(JSONDataOutputEnv, string(JSONDataOutputHash))))
switch JSONOutputMode(val) {
case JSONDataOutputHash:
return JSONDataOutputHash, nil
diff --git a/internal/inputs/totp.go b/internal/inputs/totp.go
@@ -5,8 +5,6 @@ import (
"fmt"
"net/url"
"strings"
-
- "github.com/enckse/lockbox/internal/system"
)
const (
@@ -19,7 +17,7 @@ func FormatTOTP(value string) string {
if strings.HasPrefix(value, otpAuth) {
return value
}
- override := system.EnvironOrDefault(formatTOTPEnv, "")
+ override := EnvironOrDefault(formatTOTPEnv, "")
if override != "" {
return fmt.Sprintf(override, value)
}
diff --git a/internal/platform/clipboard.go b/internal/platform/clipboard.go
@@ -10,7 +10,6 @@ import (
osc "github.com/aymanbagabas/go-osc52"
"github.com/enckse/lockbox/internal/inputs"
- "github.com/enckse/lockbox/internal/system"
)
type (
@@ -32,7 +31,7 @@ func newClipboard(copying, pasting []string) (Clipboard, error) {
}
func overrideCommand(v string) ([]string, error) {
- value := system.EnvironOrDefault(v, "")
+ value := inputs.EnvironOrDefault(v, "")
if strings.TrimSpace(value) == "" {
return nil, nil
}
diff --git a/internal/system/env.go b/internal/system/env.go
@@ -1,53 +0,0 @@
-// Package system handles simple environment variable processing
-package system
-
-import (
- "os"
- "strings"
-)
-
-const (
- // Yes is the string expected for yes values
- Yes = "yes"
- // No is the string expected for no values
- No = "no"
-)
-
-type (
- // ReadValue is the output of reading a known bool/yes/no
- ReadValue uint
-)
-
-const (
- // UnknownValue indicates an unknown value was read
- UnknownValue ReadValue = iota
- // YesValue means yes was set
- YesValue
- // NoValue means no was set
- NoValue
- // EmptyValue means that the value was not set (empty string)
- EmptyValue
-)
-
-// EnvironOrDefault will get the environment value OR default if env is not set.
-func EnvironOrDefault(envKey, defaultValue string) string {
- val := os.Getenv(envKey)
- if strings.TrimSpace(val) == "" {
- return defaultValue
- }
- return val
-}
-
-// EnvironValue read a simple yes/no from an environment value
-func EnvironValue(envKey string) ReadValue {
- value := strings.ToLower(strings.TrimSpace(os.Getenv(envKey)))
- switch value {
- case No:
- return NoValue
- case Yes:
- return YesValue
- case "":
- return EmptyValue
- }
- return UnknownValue
-}
diff --git a/internal/system/env_test.go b/internal/system/env_test.go
@@ -1,54 +0,0 @@
-package system_test
-
-import (
- "os"
- "testing"
-
- "github.com/enckse/lockbox/internal/system"
-)
-
-func TestEnvDefault(t *testing.T) {
- os.Clearenv()
- val := system.EnvironOrDefault("TEST", "value")
- if val != "value" {
- t.Error("invalid read")
- }
- os.Setenv("TEST", " ")
- val = system.EnvironOrDefault("TEST", "value")
- if val != "value" {
- t.Error("invalid read")
- }
- os.Setenv("TEST", " a")
- val = system.EnvironOrDefault("TEST", "value")
- if val != " a" {
- t.Error("invalid read")
- }
-}
-
-func TestReadValue(t *testing.T) {
- os.Clearenv()
- val := system.EnvironValue("test")
- if val != system.EmptyValue {
- t.Error("bad read")
- }
- os.Setenv("TEST", "a")
- val = system.EnvironValue("TEST")
- if val != system.UnknownValue {
- t.Error("bad read")
- }
- os.Setenv("TEST", " YeS ")
- val = system.EnvironValue("TEST")
- if val != system.YesValue {
- t.Error("bad read")
- }
- os.Setenv("TEST", " NO ")
- val = system.EnvironValue("TEST")
- if val != system.NoValue {
- t.Error("bad read")
- }
- os.Setenv("TEST", "FALSESSS")
- val = system.EnvironValue("TEST")
- if val != system.UnknownValue {
- t.Error("bad read")
- }
-}
diff --git a/internal/totp/core.go b/internal/totp/core.go
@@ -14,7 +14,6 @@ import (
"github.com/enckse/lockbox/internal/backend"
"github.com/enckse/lockbox/internal/inputs"
"github.com/enckse/lockbox/internal/platform"
- "github.com/enckse/lockbox/internal/system"
coreotp "github.com/pquerna/otp"
otp "github.com/pquerna/otp/totp"
)
@@ -84,7 +83,7 @@ func clear() {
}
func colorWhenRules() ([]inputs.ColorWindow, error) {
- envTime := system.EnvironOrDefault(inputs.ColorBetweenEnv, inputs.TOTPDefaultBetween)
+ envTime := inputs.EnvironOrDefault(inputs.ColorBetweenEnv, inputs.TOTPDefaultBetween)
if envTime == inputs.TOTPDefaultBetween {
return inputs.TOTPDefaultColorWindow, nil
}
@@ -158,7 +157,7 @@ func (args *Arguments) display(opts Options) error {
if err != nil {
return err
}
- runString := system.EnvironOrDefault(inputs.MaxTOTPTime, inputs.MaxTOTPTimeDefault)
+ runString := inputs.EnvironOrDefault(inputs.MaxTOTPTime, inputs.MaxTOTPTimeDefault)
runFor, err := strconv.Atoi(runString)
if err != nil {
return err