summaryrefslogtreecommitdiff
path: root/go/internal/command/discover
diff options
context:
space:
mode:
authorBob Van Landuyt <bob@vanlanduyt.co>2019-03-07 10:58:37 +0100
committerBob Van Landuyt <bob@vanlanduyt.co>2019-03-14 12:18:07 +0100
commit53511f3655a5eed9976164fbd88d14df3490000c (patch)
treeb46d8d7ccee0d21f9d5e8df3af02b6f37db5852d /go/internal/command/discover
parent049beb74303a03d9fa598d23b150e0ccea3cd60d (diff)
downloadgitlab-shell-53511f3655a5eed9976164fbd88d14df3490000c.tar.gz
Detect user based on key, username or id
This allows gitlab-shell to be called with an argument of the format `key-123` or `username-name`. When called in this way, `gitlab-shell` will call the GitLab internal API. If the API responds with user information, it will print a welcome message including the username. If the API responds with a successful but empty response, gitlab-shell will print a welcome message for an anonymous user. If the API response includes an error message in JSON, this message will be printed to stderr. If the API call fails, an error message including the status code will be printed to stderr.
Diffstat (limited to 'go/internal/command/discover')
-rw-r--r--go/internal/command/discover/discover.go37
-rw-r--r--go/internal/command/discover/discover_test.go130
2 files changed, 166 insertions, 1 deletions
diff --git a/go/internal/command/discover/discover.go b/go/internal/command/discover/discover.go
index 63a7a32..ab04cbd 100644
--- a/go/internal/command/discover/discover.go
+++ b/go/internal/command/discover/discover.go
@@ -2,9 +2,12 @@ package discover
import (
"fmt"
+ "io"
+ "os"
"gitlab.com/gitlab-org/gitlab-shell/go/internal/command/commandargs"
"gitlab.com/gitlab-org/gitlab-shell/go/internal/config"
+ "gitlab.com/gitlab-org/gitlab-shell/go/internal/gitlabnet/discover"
)
type Command struct {
@@ -12,6 +15,38 @@ type Command struct {
Args *commandargs.CommandArgs
}
+var (
+ output io.Writer = os.Stdout
+)
+
func (c *Command) Execute() error {
- return fmt.Errorf("No feature is implemented yet")
+ response, err := c.getUserInfo()
+ if err != nil {
+ return fmt.Errorf("Failed to get username: %v", err)
+ }
+
+ if response.IsAnonymous() {
+ fmt.Fprintf(output, "Welcome to GitLab, Anonymous!\n")
+ } else {
+ fmt.Fprintf(output, "Welcome to GitLab, @%s!\n", response.Username)
+ }
+
+ return nil
+}
+
+func (c *Command) getUserInfo() (*discover.Response, error) {
+ client, err := discover.NewClient(c.Config)
+ if err != nil {
+ return nil, err
+ }
+
+ if c.Args.GitlabKeyId != "" {
+ return client.GetByKeyId(c.Args.GitlabKeyId)
+ } else if c.Args.GitlabUsername != "" {
+ return client.GetByUsername(c.Args.GitlabUsername)
+ } else {
+ // There was no 'who' information, this matches the ruby error
+ // message.
+ return nil, fmt.Errorf("who='' is invalid")
+ }
}
diff --git a/go/internal/command/discover/discover_test.go b/go/internal/command/discover/discover_test.go
new file mode 100644
index 0000000..752e76e
--- /dev/null
+++ b/go/internal/command/discover/discover_test.go
@@ -0,0 +1,130 @@
+package discover
+
+import (
+ "bytes"
+ "encoding/json"
+ "fmt"
+ "net/http"
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+
+ "gitlab.com/gitlab-org/gitlab-shell/go/internal/command/commandargs"
+ "gitlab.com/gitlab-org/gitlab-shell/go/internal/config"
+ "gitlab.com/gitlab-org/gitlab-shell/go/internal/gitlabnet/testserver"
+)
+
+var (
+ testConfig = &config.Config{GitlabUrl: "http+unix://" + testserver.TestSocket}
+ requests = []testserver.TestRequestHandler{
+ {
+ Path: "/api/v4/internal/discover",
+ Handler: func(w http.ResponseWriter, r *http.Request) {
+ if r.URL.Query().Get("key_id") == "1" || r.URL.Query().Get("username") == "alex-doe" {
+ body := map[string]interface{}{
+ "id": 2,
+ "username": "alex-doe",
+ "name": "Alex Doe",
+ }
+ json.NewEncoder(w).Encode(body)
+ } else if r.URL.Query().Get("username") == "broken_message" {
+ body := map[string]string{
+ "message": "Forbidden!",
+ }
+ w.WriteHeader(http.StatusForbidden)
+ json.NewEncoder(w).Encode(body)
+ } else if r.URL.Query().Get("username") == "broken" {
+ w.WriteHeader(http.StatusInternalServerError)
+ } else {
+ fmt.Fprint(w, "null")
+ }
+ },
+ },
+ }
+)
+
+func TestExecute(t *testing.T) {
+ cleanup, err := testserver.StartSocketHttpServer(requests)
+ require.NoError(t, err)
+ defer cleanup()
+
+ testCases := []struct {
+ desc string
+ arguments *commandargs.CommandArgs
+ expectedOutput string
+ }{
+ {
+ desc: "With a known username",
+ arguments: &commandargs.CommandArgs{GitlabUsername: "alex-doe"},
+ expectedOutput: "Welcome to GitLab, @alex-doe!\n",
+ },
+ {
+ desc: "With a known key id",
+ arguments: &commandargs.CommandArgs{GitlabKeyId: "1"},
+ expectedOutput: "Welcome to GitLab, @alex-doe!\n",
+ },
+ {
+ desc: "With an unknown key",
+ arguments: &commandargs.CommandArgs{GitlabKeyId: "-1"},
+ expectedOutput: "Welcome to GitLab, Anonymous!\n",
+ },
+ {
+ desc: "With an unknown username",
+ arguments: &commandargs.CommandArgs{GitlabUsername: "unknown"},
+ expectedOutput: "Welcome to GitLab, Anonymous!\n",
+ },
+ }
+
+ for _, tc := range testCases {
+ t.Run(tc.desc, func(t *testing.T) {
+ buffer := &bytes.Buffer{}
+ output = buffer
+ cmd := &Command{Config: testConfig, Args: tc.arguments}
+
+ err := cmd.Execute()
+
+ assert.NoError(t, err)
+ assert.Equal(t, tc.expectedOutput, buffer.String())
+ })
+ }
+}
+
+func TestFailingExecute(t *testing.T) {
+ cleanup, err := testserver.StartSocketHttpServer(requests)
+ require.NoError(t, err)
+ defer cleanup()
+
+ testCases := []struct {
+ desc string
+ arguments *commandargs.CommandArgs
+ expectedError string
+ }{
+ {
+ desc: "With missing arguments",
+ arguments: &commandargs.CommandArgs{},
+ expectedError: "Failed to get username: who='' is invalid",
+ },
+ {
+ desc: "When the API returns an error",
+ arguments: &commandargs.CommandArgs{GitlabUsername: "broken_message"},
+ expectedError: "Failed to get username: Forbidden!",
+ },
+ {
+ desc: "When the API fails",
+ arguments: &commandargs.CommandArgs{GitlabUsername: "broken"},
+ expectedError: "Failed to get username: Internal API error (500)",
+ },
+ }
+
+ for _, tc := range testCases {
+ t.Run(tc.desc, func(t *testing.T) {
+ cmd := &Command{Config: testConfig, Args: tc.arguments}
+
+ err := cmd.Execute()
+
+ assert.EqualError(t, err, tc.expectedError)
+ })
+ }
+
+}