Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 95 additions & 0 deletions plugins/localxpose/access_token.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package localxpose

import (
"context"

"github.com/99designs/keyring"

"github.com/1Password/shell-plugins/sdk"
"github.com/1Password/shell-plugins/sdk/importer"
"github.com/1Password/shell-plugins/sdk/provision"
"github.com/1Password/shell-plugins/sdk/schema"
"github.com/1Password/shell-plugins/sdk/schema/credname"
"github.com/1Password/shell-plugins/sdk/schema/fieldname"
)

const (
serviceName = "https://loclx.io"
keyringKeyName = "token"
tokenFilePath = "~/.localxpose/.access"
)

func AccessToken() schema.CredentialType {
return schema.CredentialType{
Name: credname.AccessToken,
DocsURL: sdk.URL("https://localxpose.io/docs"),
ManagementURL: sdk.URL("https://localxpose.io/dashboard/access"),
Fields: []schema.CredentialField{
{
Name: fieldname.AccessToken,
MarkdownDescription: "Token used to authenticate to LocalXpose.",
Secret: true,
Composition: &schema.ValueComposition{
Length: 40,
Charset: schema.Charset{
Uppercase: true,
Lowercase: true,
Digits: true,
},
},
},
},
DefaultProvisioner: provision.EnvVars(defaultEnvVarMapping),
Importer: importer.TryAll(
importer.TryEnvVarPair(defaultEnvVarMapping),
TryOSKeyring(),
TryAccessTokenFile(),
)}
}

var defaultEnvVarMapping = map[string]sdk.FieldName{
"LX_ACCESS_TOKEN": fieldname.AccessToken,
}

func TryAccessTokenFile() sdk.Importer {
return importer.TryFile(tokenFilePath, func(ctx context.Context, contents importer.FileContents, in sdk.ImportInput, out *sdk.ImportAttempt) {
if contents.ToString() == "" {
return
}
out.AddCandidate(sdk.ImportCandidate{
Fields: map[sdk.FieldName]string{
fieldname.AccessToken: contents.ToString(),
},
})
})
}

func TryOSKeyring() sdk.Importer {
return func(ctx context.Context, in sdk.ImportInput, out *sdk.ImportOutput) {
availableBackends := keyring.AvailableBackends()
if len(availableBackends) == 0 {
return
}
for _, backendType := range availableBackends {
attempt := out.NewAttempt(importer.SourceOther(string(backendType), ""))
openKeyring, err := keyring.Open(keyring.Config{
KeychainTrustApplication: true,
ServiceName: serviceName,
})
if err != nil {
attempt.AddError(err)
return
}
key, err := openKeyring.Get(keyringKeyName)
if err != nil {
attempt.AddError(err)
continue
}
attempt.AddCandidate(sdk.ImportCandidate{
Fields: map[sdk.FieldName]string{
fieldname.AccessToken: string(key.Data),
},
})
}
}
}
53 changes: 53 additions & 0 deletions plugins/localxpose/access_token_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package localxpose

import (
"testing"

"github.com/1Password/shell-plugins/sdk"
"github.com/1Password/shell-plugins/sdk/plugintest"
"github.com/1Password/shell-plugins/sdk/schema/fieldname"
)

func TestAccessTokenProvisioner(t *testing.T) {
plugintest.TestProvisioner(t, AccessToken().DefaultProvisioner, map[string]plugintest.ProvisionCase{
"default": {
ItemFields: map[sdk.FieldName]string{
fieldname.AccessToken: "PROVISIONERqLtcqQ8a3oRVfK5tiHzDOhEXAMPLE",
},
ExpectedOutput: sdk.ProvisionOutput{
Environment: map[string]string{
"LX_ACCESS_TOKEN": "PROVISIONERqLtcqQ8a3oRVfK5tiHzDOhEXAMPLE",
},
},
},
})
}

func TestAccessTokenImporter(t *testing.T) {
expectedFields := map[sdk.FieldName]string{
fieldname.AccessToken: "31QJpgl8FB9qLtcqQ8a3oRVfK5tiHzDOhEXAMPLE",
}

plugintest.TestImporter(t, AccessToken().Importer, map[string]plugintest.ImportCase{
"environment": {
Environment: map[string]string{
"LX_ACCESS_TOKEN": "31QJpgl8FB9qLtcqQ8a3oRVfK5tiHzDOhEXAMPLE",
},
ExpectedCandidates: []sdk.ImportCandidate{
{
Fields: expectedFields,
},
},
},
"file": {
Files: map[string]string{
"~/.localxpose/.access": plugintest.LoadFixture(t, "localxpose.access"),
},
ExpectedCandidates: []sdk.ImportCandidate{
{
Fields: expectedFields,
},
},
},
})
}
36 changes: 36 additions & 0 deletions plugins/localxpose/localxpose.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package localxpose

import (
"github.com/1Password/shell-plugins/sdk"
"github.com/1Password/shell-plugins/sdk/needsauth"
"github.com/1Password/shell-plugins/sdk/schema"
"github.com/1Password/shell-plugins/sdk/schema/credname"
)

func LocalXposeCLI() schema.Executable {
return schema.Executable{
Name: "LocalXpose CLI",
Runs: []string{"loclx"},
DocsURL: sdk.URL("https://localxpose.io/docs/cli"),
NeedsAuth: needsauth.IfAll(
needsauth.NotForHelpOrVersion(),
needsauth.NotWhenContainsArgs("account", "login"), // skip 1Password authentication for "loclx account login" and its subcommands
needsauth.NotWhenContainsArgs("a", "login"), // skip 1Password authentication for "loclx account login" and its subcommands
needsauth.NotWhenContainsArgs("account", "logout"), // skip 1Password authentication for "loclx account logout" and its subcommands
needsauth.NotWhenContainsArgs("a", "logout"), // skip 1Password authentication for "loclx account logout" and its subcommands
needsauth.NotWhenContainsArgs("service", "restart"), // skip 1Password authentication for "loclx service restart" and its subcommands
needsauth.NotWhenContainsArgs("service", "start"), // skip 1Password authentication for "loclx service start" and its subcommands
needsauth.NotWhenContainsArgs("service", "status"), // skip 1Password authentication for "loclx service status" and its subcommands
needsauth.NotWhenContainsArgs("service", "stop"), // skip 1Password authentication for "loclx service stop" and its subcommands
needsauth.NotWhenContainsArgs("service", "uninstall"), // skip 1Password authentication for "loclx service uninstall" and its subcommands
needsauth.NotWhenContainsArgs("setting"), // skip 1Password authentication for "loclx setting" and its subcommands
needsauth.NotWhenContainsArgs("update"), // skip 1Password authentication for "loclx update" and its subcommands
needsauth.NotWithoutArgs(),
),
Uses: []schema.CredentialUsage{
{
Name: credname.AccessToken,
},
},
}
}
22 changes: 22 additions & 0 deletions plugins/localxpose/plugin.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package localxpose

import (
"github.com/1Password/shell-plugins/sdk"
"github.com/1Password/shell-plugins/sdk/schema"
)

func New() schema.Plugin {
return schema.Plugin{
Name: "localxpose",
Platform: schema.PlatformInfo{
Name: "LocalXpose",
Homepage: sdk.URL("https://localxpose.io"),
},
Credentials: []schema.CredentialType{
AccessToken(),
},
Executables: []schema.Executable{
LocalXposeCLI(),
},
}
}
1 change: 1 addition & 0 deletions plugins/localxpose/test-fixtures/localxpose.access
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
31QJpgl8FB9qLtcqQ8a3oRVfK5tiHzDOhEXAMPLE