diff --git a/go.mod b/go.mod index 7502337..1305ba8 100644 --- a/go.mod +++ b/go.mod @@ -2,4 +2,4 @@ module go.jolheiser.com/spectre go 1.17 -require golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa // indirect +require golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa diff --git a/go.sum b/go.sum index a6458a0..49ae2ce 100644 --- a/go.sum +++ b/go.sum @@ -1,2 +1,13 @@ golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa h1:idItI2DDfCokpg0N51B2VtiLdJ4vAuXC9fnCb2gACo4= golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 h1:qWPm9rbaAMKs8Bq/9LRpbMqxWRVUAQwMI9fVrssnTfw= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 h1:SrN+KX8Art/Sf4HNj6Zcz06G7VEz+7w9tdXTPOZ7+l4= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e h1:FDhOuMEY4JVRztM/gsbk+IKUQ8kj74bxZrgw87eMMVc= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/scope.go b/scope.go index a23f936..7cd8baa 100644 --- a/scope.go +++ b/scope.go @@ -14,13 +14,13 @@ type Scoper interface { Scope(Scope) string } -// SimpleScope is a simple Scoper -type SimpleScope struct { +// SimpleScoper is a simple Scoper +type SimpleScoper struct { Key string } // Scope fulfills Scoper -func (s SimpleScope) Scope(scope Scope) string { +func (s SimpleScoper) Scope(scope Scope) string { switch scope { case Identification: return s.Key + ".login" @@ -32,3 +32,8 @@ func (s SimpleScope) Scope(scope Scope) string { return s.Key } } + +// DefaultScoper is the default Scoper +var DefaultScoper = SimpleScoper{ + Key: "com.lyndir.masterpassword", +} diff --git a/spectre.go b/spectre.go index d960726..db642df 100644 --- a/spectre.go +++ b/spectre.go @@ -17,16 +17,29 @@ type Spectre struct { } // New returns a Spectre client -func New(name, secret string, scoper Scoper) (s *Spectre, err error) { +func New(name, secret string, opts ...SpectreOption) (s *Spectre, err error) { s = &Spectre{ name: name, secret: secret, - scoper: scoper, + scoper: DefaultScoper, + } + for _, opt := range opts { + opt(s) } s.key, err = s.userKey() return } +// SpectreOption is a Spectre option +type SpectreOption func(*Spectre) + +// WithScoper assigns a scoper to Spectre +func WithScoper(scoper Scoper) SpectreOption { + return func(s *Spectre) { + s.scoper = scoper + } +} + func (s *Spectre) userKey() ([]byte, error) { nameBytes := []byte(s.name) secretBytes := []byte(s.secret) diff --git a/spectre_test.go b/spectre_test.go index d164e0a..27deb2d 100644 --- a/spectre_test.go +++ b/spectre_test.go @@ -4,7 +4,6 @@ import ( _ "embed" "encoding/xml" "strconv" - "strings" "testing" ) @@ -15,16 +14,13 @@ func TestSpectre(t *testing.T) { t.FailNow() } - scoper := SimpleScope{ - Key: "com.lyndir.masterpassword", - } dc := tests.Cases[0] for _, tc := range tests.Cases[1:] { t.Run(tc.ID, func(t *testing.T) { user := def(dc.UserName, tc.UserName) secret := def(dc.UserSecret, tc.UserSecret) - s, err := New(user, secret, scoper) + s, err := New(user, secret) if err != nil { t.Logf("could not initialize spectre: %v", err) t.Fail() @@ -46,7 +42,7 @@ func TestSpectre(t *testing.T) { WithScope(Scope(scope)), ) - if !strings.EqualFold(pass, tc.Result) { + if pass != tc.Result { t.Log("passwords did not match") t.Fail() } @@ -54,6 +50,21 @@ func TestSpectre(t *testing.T) { } } +// From the website sanity check +func TestSanity(t *testing.T) { + s, err := New("Robert Lee Mitchell", "banana colored duckling") + if err != nil { + t.Logf("failed sanity check: %v", err) + t.FailNow() + } + + pw := s.Site("masterpasswordapp.com") + if pw != "Jejr5[RepuSosp" { + t.Log("failed sanity check") + t.FailNow() + } +} + //go:embed spectre_tests.xml var testsXML []byte