diff --git a/pkg/cmd/me.go b/pkg/cmd/me.go new file mode 100644 index 00000000..894cc8a6 --- /dev/null +++ b/pkg/cmd/me.go @@ -0,0 +1,48 @@ +/* +Copyright © 2023 Doppler + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +package cmd + +import ( + "github.com/DopplerHQ/cli/pkg/configuration" + "github.com/DopplerHQ/cli/pkg/http" + "github.com/DopplerHQ/cli/pkg/printer" + "github.com/DopplerHQ/cli/pkg/utils" + "github.com/spf13/cobra" +) + +var meCmd = &cobra.Command{ + Use: "me", + Aliases: []string{"whoami"}, + Short: "Get info about the currently authenticated entity", + Args: cobra.NoArgs, + Run: func(cmd *cobra.Command, args []string) { + jsonFlag := utils.OutputJSON + localConfig := configuration.LocalConfig(cmd) + + utils.RequireValue("token", localConfig.Token.Value) + + info, err := http.GetActorInfo(localConfig.APIHost.Value, utils.GetBool(localConfig.VerifyTLS.Value, true), localConfig.Token.Value) + if !err.IsNil() { + utils.HandleError(err.Unwrap(), err.Message) + } + + printer.ActorInfo(info, jsonFlag) + }, +} + +func init() { + rootCmd.AddCommand(meCmd) +} diff --git a/pkg/http/api.go b/pkg/http/api.go index 9c77d32b..847cd119 100644 --- a/pkg/http/api.go +++ b/pkg/http/api.go @@ -1299,3 +1299,23 @@ func ImportTemplate(host string, verifyTLS bool, apiKey string, template []byte) } return info, Error{} } + +func GetActorInfo(host string, verifyTLS bool, apiKey string) (models.ActorInfo, Error) { + url, err := generateURL(host, "/v3/me", nil) + if err != nil { + return models.ActorInfo{}, Error{Err: err, Message: "Unable to generate url"} + } + + statusCode, _, response, err := GetRequest(url, verifyTLS, apiKeyHeader(apiKey)) + if err != nil { + return models.ActorInfo{}, Error{Err: err, Message: "Unable to fetch actor", Code: statusCode} + } + + var info models.ActorInfo + err = json.Unmarshal(response, &info) + if err != nil { + return models.ActorInfo{}, Error{Err: err, Message: "Unable to parse API response", Code: statusCode} + } + + return info, Error{} +} diff --git a/pkg/models/api.go b/pkg/models/api.go index c413f10b..d838174c 100644 --- a/pkg/models/api.go +++ b/pkg/models/api.go @@ -134,3 +134,11 @@ type APISecret struct { ComputedVisibility string `json:"computedVisibility"` Note string `json:"note"` } + +type ActorInfo struct { + Workplace ActorWorkplaceInfo `json:"workplace"` +} +type ActorWorkplaceInfo struct { + Name string `json:"name"` + Slug string `json:"slug"` +} diff --git a/pkg/printer/enclave.go b/pkg/printer/enclave.go index 5767ee0c..b3ec5dcb 100644 --- a/pkg/printer/enclave.go +++ b/pkg/printer/enclave.go @@ -428,3 +428,13 @@ func ConfigServiceToken(token models.ConfigServiceToken, jsonFlag bool, plain bo rows := [][]string{{token.Name, token.Token, token.Slug, token.Project, token.Environment, token.Config, token.CreatedAt, token.ExpiresAt, token.Access}} Table([]string{"name", "token", "slug", "project", "environment", "config", "created at", "expires at", "access"}, rows, TableOptions()) } + +func ActorInfo(info models.ActorInfo, jsonFlag bool) { + if jsonFlag { + JSON(info) + return + } + + rows := [][]string{{fmt.Sprintf("%s (%s)", info.Workplace.Name, info.Workplace.Slug)}} + Table([]string{"workplace"}, rows, TableOptions()) +} diff --git a/tests/e2e.sh b/tests/e2e.sh index ba5e5e77..2c6d9601 100755 --- a/tests/e2e.sh +++ b/tests/e2e.sh @@ -21,6 +21,7 @@ export DOPPLER_CONFIG="e2e" "$DIR/e2e/legacy-commands.sh" "$DIR/e2e/analytics.sh" "$DIR/e2e/setup.sh" +"$DIR/e2e/me.sh" echo -e "\nAll tests completed successfully!" exit 0 diff --git a/tests/e2e/me.sh b/tests/e2e/me.sh new file mode 100755 index 00000000..cb69b663 --- /dev/null +++ b/tests/e2e/me.sh @@ -0,0 +1,40 @@ +#!/bin/bash + +set -euo pipefail + +TEST_NAME="me" + +cleanup() { + exit_code=$? + if [ "$exit_code" -ne 0 ]; then + echo "ERROR: '$TEST_NAME' tests failed during execution" + afterAll || echo "ERROR: Cleanup failed" + fi + + exit "$exit_code" +} +trap cleanup EXIT + +beforeAll() { + echo "INFO: Executing '$TEST_NAME' tests" +} + +afterAll() { + echo "INFO: Completed '$TEST_NAME' tests" +} + +error() { + message=$1 + echo "$message" + exit 1 +} + +beforeAll + +# verify valid token exit code +"$DOPPLER_BINARY" me >/dev/null || error "ERROR: valid token produced error" + +# verify invalid token exit code +DOPPLER_TOKEN="invalid" "$DOPPLER_BINARY" me >/dev/null && error "ERROR: invalid token did not produce error" + +afterAll