Skip to content
Merged
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
30 changes: 30 additions & 0 deletions plugins/netlify/netlify.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package netlify

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 NetlifyCLI() schema.Executable {
return schema.Executable{
Name: "Netlify CLI",
Runs: []string{"netlify"},
DocsURL: sdk.URL("https://cli.netlify.com"),
NeedsAuth: needsauth.IfAll(
needsauth.NotForHelpOrVersion(),
needsauth.NotWithoutArgs(),
needsauth.NotWhenContainsArgs("login"),
needsauth.NotForExactArgs("logout"),
needsauth.NotWhenContainsArgs("switch"),
needsauth.NotWhenContainsArgs("completion"),
needsauth.NotWhenContainsArgs("unlink"),
),
Uses: []schema.CredentialUsage{
{
Name: credname.PersonalAccessToken,
},
},
}
}
71 changes: 71 additions & 0 deletions plugins/netlify/personal_access_token.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package netlify

import (
"context"

"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"
)

func PersonalAccessToken() schema.CredentialType {
return schema.CredentialType{
Name: credname.PersonalAccessToken,
DocsURL: sdk.URL("https://docs.netlify.com/api-and-cli-guides/cli-guides/get-started-with-cli"),
ManagementURL: sdk.URL("https://app.netlify.com/user/applications#personal-access-tokens"),
Fields: []schema.CredentialField{
{
Name: fieldname.Token,
MarkdownDescription: "Token used to authenticate to Netlify.",
Secret: true,
},
},
DefaultProvisioner: provision.EnvVars(defaultEnvVarMapping),
Importer: importer.TryAll(
importer.TryEnvVarPair(defaultEnvVarMapping),
importer.MacOnly(TryNetlifyConfigFile("~/Library/Preferences/netlify/config.json")),
importer.LinuxOnly(TryNetlifyConfigFile("~/.config/netlify/config.json")),
),
}
}

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

// TryNetlifyConfigFile imports the token that `netlify login` stores in the global config.json,
// under users.<userId>.auth.token for the active userId.
func TryNetlifyConfigFile(path string) sdk.Importer {
return importer.TryFile(path, func(ctx context.Context, contents importer.FileContents, in sdk.ImportInput, out *sdk.ImportAttempt) {
var config Config
if err := contents.ToJSON(&config); err != nil {
out.AddError(err)
return
}

user, ok := config.Users[config.UserID]
if !ok || user.Auth.Token == "" {
return
}

out.AddCandidate(sdk.ImportCandidate{
Fields: map[sdk.FieldName]string{
fieldname.Token: user.Auth.Token,
},
})
})
}

type Config struct {
UserID string `json:"userId"`
Users map[string]ConfigUser `json:"users"`
}

type ConfigUser struct {
Auth struct {
Token string `json:"token"`
} `json:"auth"`
}
74 changes: 74 additions & 0 deletions plugins/netlify/personal_access_token_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package netlify

import (
"testing"

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

func TestPersonalAccessTokenProvisioner(t *testing.T) {
plugintest.TestProvisioner(t, PersonalAccessToken().DefaultProvisioner, map[string]plugintest.ProvisionCase{
"default": {
ItemFields: map[sdk.FieldName]string{
fieldname.Token: "kV9wTq3ZtN0aB4cD7eF1gH5iJ8kL2mN6oP0qR4sT8uVexample",
},
ExpectedOutput: sdk.ProvisionOutput{
Environment: map[string]string{
"NETLIFY_AUTH_TOKEN": "kV9wTq3ZtN0aB4cD7eF1gH5iJ8kL2mN6oP0qR4sT8uVexample",
},
},
},
})
}

func TestPersonalAccessTokenImporter(t *testing.T) {
plugintest.TestImporter(t, PersonalAccessToken().Importer, map[string]plugintest.ImportCase{
"environment": {
Environment: map[string]string{
"NETLIFY_AUTH_TOKEN": "kV9wTq3ZtN0aB4cD7eF1gH5iJ8kL2mN6oP0qR4sT8uV",
},
ExpectedCandidates: []sdk.ImportCandidate{
{
Fields: map[sdk.FieldName]string{
fieldname.Token: "kV9wTq3ZtN0aB4cD7eF1gH5iJ8kL2mN6oP0qR4sT8uV",
},
},
},
},
"config file (macOS)": {
OS: "darwin",
Files: map[string]string{
"~/Library/Preferences/netlify/config.json": plugintest.LoadFixture(t, "config.json"),
},
ExpectedCandidates: []sdk.ImportCandidate{
{
Fields: map[sdk.FieldName]string{
fieldname.Token: "nfp_kV9wTq3ZtN0aB4cD7eF1gH5iJ8kL2mN6EXAMPLE",
},
},
},
},
"config file (Linux)": {
OS: "linux",
Files: map[string]string{
"~/.config/netlify/config.json": plugintest.LoadFixture(t, "config.json"),
},
ExpectedCandidates: []sdk.ImportCandidate{
{
Fields: map[sdk.FieldName]string{
fieldname.Token: "nfp_kV9wTq3ZtN0aB4cD7eF1gH5iJ8kL2mN6EXAMPLE",
},
},
},
},
"config file (logged out)": {
OS: "darwin",
Files: map[string]string{
"~/Library/Preferences/netlify/config.json": `{"telemetryDisabled": false, "cliId": "55f2daf5-ee38-4fa0-8fd8-e67892a123d6", "userId": null}`,
},
ExpectedCandidates: nil,
},
})
}
22 changes: 22 additions & 0 deletions plugins/netlify/plugin.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package netlify

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

func New() schema.Plugin {
return schema.Plugin{
Name: "netlify",
Platform: schema.PlatformInfo{
Name: "Netlify",
Homepage: sdk.URL("https://netlify.com"),
},
Credentials: []schema.CredentialType{
PersonalAccessToken(),
},
Executables: []schema.Executable{
NetlifyCLI(),
},
}
}
16 changes: 16 additions & 0 deletions plugins/netlify/test-fixtures/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"telemetryDisabled": false,
"cliId": "55f2daf5-ee38-4fa0-8fd8-e67892a123d6",
"userId": "5f3a1b2c4d5e6f7a8b9c0d1e",
"users": {
"5f3a1b2c4d5e6f7a8b9c0d1e": {
"id": "5f3a1b2c4d5e6f7a8b9c0d1e",
"name": "Wendy Appleseed",
"email": "wendy.appleseed@example.com",
"auth": {
"token": "nfp_kV9wTq3ZtN0aB4cD7eF1gH5iJ8kL2mN6EXAMPLE",
"github": {}
}
}
}
}
Loading