From ae2f942ef907161af0aba5f3511db72cf9801dca Mon Sep 17 00:00:00 2001 From: Michael Muré Date: Sun, 12 Jan 2020 16:38:16 +0100 Subject: more wip --- bridge/core/auth/credential.go | 4 ++-- bridge/core/auth/credential_test.go | 41 ++++++++++++++------------------- bridge/core/config.go | 1 + bridge/github/config.go | 8 +++++-- bridge/github/config_test.go | 5 ++--- bridge/github/export.go | 45 +++++++++++++------------------------ bridge/github/import.go | 16 +------------ bridge/github/import_test.go | 8 +------ input/prompt.go | 2 ++ 9 files changed, 47 insertions(+), 83 deletions(-) create mode 100644 bridge/core/config.go diff --git a/bridge/core/auth/credential.go b/bridge/core/auth/credential.go index 228eb006..e843ede7 100644 --- a/bridge/core/auth/credential.go +++ b/bridge/core/auth/credential.go @@ -43,7 +43,7 @@ type Credential interface { Metadata() map[string]string // Return all the specific properties of the credential that need to be saved into the configuration. - // This does not include Target, User, Kind and CreateTime. + // This does not include Target, Kind, CreateTime and Metadata. toConfig() map[string]string } @@ -134,7 +134,7 @@ func List(repo repository.RepoConfig, opts ...Option) ([]Credential, error) { return nil, err } - re, err := regexp.Compile(configKeyPrefix + `.([^.]+).([^.]+)`) + re, err := regexp.Compile(`^` + configKeyPrefix + `\.([^.]+)\.([^.]+(?:\.[^.]+)*)$`) if err != nil { panic(err) } diff --git a/bridge/core/auth/credential_test.go b/bridge/core/auth/credential_test.go index f91d273d..49c138cf 100644 --- a/bridge/core/auth/credential_test.go +++ b/bridge/core/auth/credential_test.go @@ -7,32 +7,23 @@ import ( "github.com/stretchr/testify/require" "github.com/MichaelMure/git-bug/entity" - "github.com/MichaelMure/git-bug/identity" "github.com/MichaelMure/git-bug/repository" ) func TestCredential(t *testing.T) { repo := repository.NewMockRepoForTest() - user1 := identity.NewIdentity("user1", "email") - err := user1.Commit(repo) - assert.NoError(t, err) - - user2 := identity.NewIdentity("user2", "email") - err = user2.Commit(repo) - assert.NoError(t, err) - - storeToken := func(user identity.Interface, val string, target string) *Token { - token := NewToken(user.Id(), val, target) - err = Store(repo, token) + storeToken := func(val string, target string) *Token { + token := NewToken(val, target) + err := Store(repo, token) require.NoError(t, err) return token } - token := storeToken(user1, "foobar", "github") + token := storeToken("foobar", "github") // Store + Load - err = Store(repo, token) + err := Store(repo, token) assert.NoError(t, err) token2, err := LoadWithId(repo, token.ID()) @@ -50,8 +41,8 @@ func TestCredential(t *testing.T) { token.createTime = token3.CreateTime() assert.Equal(t, token, token3) - token4 := storeToken(user1, "foo", "gitlab") - token5 := storeToken(user2, "bar", "github") + token4 := storeToken("foo", "gitlab") + token5 := storeToken("bar", "github") // List + options creds, err := List(repo, WithTarget("github")) @@ -62,14 +53,6 @@ func TestCredential(t *testing.T) { assert.NoError(t, err) sameIds(t, creds, []Credential{token4}) - creds, err = List(repo, WithUser(user1)) - assert.NoError(t, err) - sameIds(t, creds, []Credential{token, token4}) - - creds, err = List(repo, WithUserId(user1.Id())) - assert.NoError(t, err) - sameIds(t, creds, []Credential{token, token4}) - creds, err = List(repo, WithKind(KindToken)) assert.NoError(t, err) sameIds(t, creds, []Credential{token, token4, token5}) @@ -78,6 +61,16 @@ func TestCredential(t *testing.T) { assert.NoError(t, err) sameIds(t, creds, []Credential{}) + // Metadata + + token4.Metadata()["key"] = "value" + err = Store(repo, token4) + assert.NoError(t, err) + + creds, err = List(repo, WithMeta("key", "value")) + assert.NoError(t, err) + sameIds(t, creds, []Credential{token4}) + // Exist exist := IdExist(repo, token.ID()) assert.True(t, exist) diff --git a/bridge/core/config.go b/bridge/core/config.go new file mode 100644 index 00000000..9a8bc959 --- /dev/null +++ b/bridge/core/config.go @@ -0,0 +1 @@ +package core diff --git a/bridge/github/config.go b/bridge/github/config.go index e51f244b..fcb94079 100644 --- a/bridge/github/config.go +++ b/bridge/github/config.go @@ -81,7 +81,7 @@ func (g *Github) Configure(repo *cache.RepoCache, params core.BridgeParams) (cor login := params.Login if login == "" { - login, err = input.Prompt("Github login", "", true, validateUsername) + login, err = input.Prompt("Github login", "login", input.Required, validateUsername) if err != nil { return nil, err } @@ -128,6 +128,10 @@ func (g *Github) Configure(repo *cache.RepoCache, params core.BridgeParams) (cor return nil, err } + // Todo: if no user exist with the given login + // - tag the default user with the github login + // - add a command to manually tag a user ? + // don't forget to store the now known valid token if !auth.IdExist(repo, cred.ID()) { err = auth.Store(repo, cred) @@ -317,7 +321,7 @@ func promptToken() (string, error) { return "token has incorrect format", nil } - return input.Prompt("Enter token", "token", "", input.Required, validator) + return input.Prompt("Enter token", "token", input.Required, validator) } func loginAndRequestToken(login, owner, project string) (string, error) { diff --git a/bridge/github/config_test.go b/bridge/github/config_test.go index 9798d26b..d7b1b38d 100644 --- a/bridge/github/config_test.go +++ b/bridge/github/config_test.go @@ -7,7 +7,6 @@ import ( "github.com/stretchr/testify/assert" "github.com/MichaelMure/git-bug/bridge/core/auth" - "github.com/MichaelMure/git-bug/entity" ) func TestSplitURL(t *testing.T) { @@ -155,8 +154,8 @@ func TestValidateProject(t *testing.T) { t.Skip("Env var GITHUB_TOKEN_PUBLIC missing") } - tokenPrivate := auth.NewToken(entity.UnsetId, envPrivate, target) - tokenPublic := auth.NewToken(entity.UnsetId, envPublic, target) + tokenPrivate := auth.NewToken(envPrivate, target) + tokenPublic := auth.NewToken(envPublic, target) type args struct { owner string diff --git a/bridge/github/export.go b/bridge/github/export.go index 6c089a47..1cc66dee 100644 --- a/bridge/github/export.go +++ b/bridge/github/export.go @@ -7,6 +7,7 @@ import ( "fmt" "io/ioutil" "net/http" + "os" "strings" "time" @@ -19,6 +20,7 @@ import ( "github.com/MichaelMure/git-bug/bug" "github.com/MichaelMure/git-bug/cache" "github.com/MichaelMure/git-bug/entity" + "github.com/MichaelMure/git-bug/identity" "github.com/MichaelMure/git-bug/repository" ) @@ -33,13 +35,6 @@ type githubExporter struct { // cache identities clients identityClient map[entity.Id]*githubv4.Client - // the client to use for non user-specific queries - // should be the client of the default user - defaultClient *githubv4.Client - - // the token of the default user - defaultToken *auth.Token - // github repository ID repositoryID string @@ -58,43 +53,33 @@ func (ge *githubExporter) Init(repo *cache.RepoCache, conf core.Configuration) e ge.cachedOperationIDs = make(map[entity.Id]string) ge.cachedLabels = make(map[string]string) - user, err := repo.GetUserIdentity() - if err != nil { - return err - } - // preload all clients - err = ge.cacheAllClient(repo) - if err != nil { - return err - } - - ge.defaultClient, err = ge.getClientForIdentity(user.Id()) - if err != nil { - return err - } - - creds, err := auth.List(repo, auth.WithUserId(user.Id()), auth.WithTarget(target), auth.WithKind(auth.KindToken)) + err := ge.cacheAllClient(repo) if err != nil { return err } - if len(creds) == 0 { - return ErrMissingIdentityToken - } - - ge.defaultToken = creds[0].(*auth.Token) - return nil } -func (ge *githubExporter) cacheAllClient(repo repository.RepoConfig) error { +func (ge *githubExporter) cacheAllClient(repo *cache.RepoCache) error { creds, err := auth.List(repo, auth.WithTarget(target), auth.WithKind(auth.KindToken)) if err != nil { return err } for _, cred := range creds { + login, ok := cred.Metadata()[auth.MetaKeyLogin] + if !ok { + _, _ = fmt.Fprintf(os.Stderr, "credential %s is not tagged with Github login\n", cred.ID().Human()) + continue + } + + user, err := repo.ResolveIdentityImmutableMetadata(metaKeyGithubLogin, login) + if err == identity.ErrIdentityNotExist { + continue + } + if _, ok := ge.identityClient[cred.UserId()]; !ok { client := buildClient(creds[0].(*auth.Token)) ge.identityClient[cred.UserId()] = client diff --git a/bridge/github/import.go b/bridge/github/import.go index 39aebccb..aac4f119 100644 --- a/bridge/github/import.go +++ b/bridge/github/import.go @@ -12,7 +12,6 @@ import ( "github.com/MichaelMure/git-bug/bug" "github.com/MichaelMure/git-bug/cache" "github.com/MichaelMure/git-bug/entity" - "github.com/MichaelMure/git-bug/identity" "github.com/MichaelMure/git-bug/util/text" ) @@ -39,20 +38,7 @@ type githubImporter struct { func (gi *githubImporter) Init(repo *cache.RepoCache, conf core.Configuration) error { gi.conf = conf - opts := []auth.Option{ - auth.WithTarget(target), - auth.WithKind(auth.KindToken), - } - - user, err := repo.GetUserIdentity() - if err == nil { - opts = append(opts, auth.WithUserId(user.Id())) - } - if err == identity.ErrNoIdentitySet { - opts = append(opts, auth.WithUserId(auth.DefaultUserId)) - } - - creds, err := auth.List(repo, opts...) + creds, err := auth.List(repo, auth.WithTarget(target), auth.WithKind(auth.KindToken)) if err != nil { return err } diff --git a/bridge/github/import_test.go b/bridge/github/import_test.go index 57bab61e..75310ab3 100644 --- a/bridge/github/import_test.go +++ b/bridge/github/import_test.go @@ -140,13 +140,7 @@ func Test_Importer(t *testing.T) { t.Skip("Env var GITHUB_TOKEN_PRIVATE missing") } - err = author.Commit(repo) - require.NoError(t, err) - - err = identity.SetUserIdentity(repo, author) - require.NoError(t, err) - - token := auth.NewToken(author.Id(), envToken, target) + token := auth.NewToken(envToken, target) err = auth.Store(repo, token) require.NoError(t, err) diff --git a/input/prompt.go b/input/prompt.go index c7887abb..960ecd62 100644 --- a/input/prompt.go +++ b/input/prompt.go @@ -14,6 +14,8 @@ import ( ) // PromptValidator is a validator for a user entry +// If complaint is "", value is considered valid, otherwise it's the error reported to the user +// If err != nil, a terminal error happened type PromptValidator func(name string, value string) (complaint string, err error) // Required is a validator preventing a "" value -- cgit