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
47 changes: 37 additions & 10 deletions cmd/doctor/check.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"fmt"
"math/rand"
"runtime"
"slices"
"strings"
"time"

Expand All @@ -27,6 +28,7 @@ import (
"github.com/slackapi/slack-cli/internal/iostreams"
"github.com/slackapi/slack-cli/internal/pkg/version"
"github.com/slackapi/slack-cli/internal/shared"
"github.com/slackapi/slack-cli/internal/shared/types"
"github.com/slackapi/slack-cli/internal/slackerror"
"github.com/slackapi/slack-cli/internal/style"
"github.com/slackapi/slack-cli/internal/update"
Expand Down Expand Up @@ -271,32 +273,57 @@ func checkCLICreds(ctx context.Context, clients *shared.ClientFactory) (Section,
section.Errors = []slackerror.Error{*slackerror.New(slackerror.ErrNotAuthed)}
}

slices.SortStableFunc(authList, func(a types.SlackAuth, b types.SlackAuth) int {
domain := strings.Compare(a.TeamDomain, b.TeamDomain)
if domain != 0 {
return domain
}
id := strings.Compare(a.TeamID, b.TeamID)
return id
})

// Teams
if len(authList) > 0 {
authSections := []Section{}
currentAPIHost := clients.Config.APIHostResolved
caser := cases.Title(language.English)
for _, authInfo := range authList {
checkDetails := []Section{
{"Team domain", authInfo.TeamDomain, []Section{}, []slackerror.Error{}},
{"Team ID", authInfo.TeamID, []Section{}, []slackerror.Error{}},
{"User ID", authInfo.UserID, []Section{}, []slackerror.Error{}},
{
"Last updated",
authInfo.LastUpdated.Format("2006-01-02 15:04:05 Z07:00"),
[]Section{},
[]slackerror.Error{},
Label: "Team domain",
Value: authInfo.TeamDomain,
},
{
Label: "Team ID",
Value: authInfo.TeamID,
},
{
Label: "User ID",
Value: authInfo.UserID,
},
{
Label: "Last updated",
Value: authInfo.LastUpdated.Format("2006-01-02 15:04:05 Z07:00"),
},
{
Label: "Authorization level",
Value: caser.String(authInfo.AuthLevel()),
},
{"Authorization level", caser.String(authInfo.AuthLevel()), []Section{}, []slackerror.Error{}},
}

if authInfo.APIHost != nil {
hostSection := Section{"API Host", *authInfo.APIHost, []Section{}, []slackerror.Error{}}
hostSection := Section{
Label: "API Host",
Value: *authInfo.APIHost,
}
checkDetails = append(checkDetails, hostSection)
}

// Validate session token
validitySection := Section{"Token status", "Valid", []Section{}, []slackerror.Error{}}
validitySection := Section{
Label: "Token status",
Value: "Valid",
}

// TODO :: .ValidateSession() utilizes the host (APIHost) assigned to the client making
// the call. This results in incorrectly deeming tokens invalid if using multiple workspaces
Expand Down
136 changes: 131 additions & 5 deletions cmd/doctor/check_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"runtime"
"testing"

"github.com/slackapi/slack-cli/internal/api"
"github.com/slackapi/slack-cli/internal/config"
"github.com/slackapi/slack-cli/internal/deputil"
"github.com/slackapi/slack-cli/internal/hooks"
Expand Down Expand Up @@ -294,23 +295,148 @@ func TestDoctorCheckCLIConfig(t *testing.T) {
}

func TestDoctorCheckCLICreds(t *testing.T) {
mockAPIHost := "https://example.com/api/"
tests := map[string]struct {
auths types.SlackAuth
mockAuths []types.SlackAuth
expectedSections []Section
expectedErrorSection []slackerror.Error
}{
"errors without available authorizations": {},
"errors without available authorizations": {
expectedErrorSection: []slackerror.Error{*slackerror.New(slackerror.ErrNotAuthed)},
expectedSections: []Section{},
},
"orders multiple different authentications": {
mockAuths: []types.SlackAuth{
{
TeamDomain: "teamB",
TeamID: "T002",
UserID: "U002",
},
{
TeamDomain: "teamB",
TeamID: "E003",
EnterpriseID: "E003",
IsEnterpriseInstall: true,
UserID: "U003",
},
{
APIHost: &mockAPIHost,
TeamDomain: "teamA",
TeamID: "T004",
UserID: "U004",
},
},
expectedSections: []Section{
{
Subsections: []Section{
{
Label: "Team domain",
Value: "teamA",
},
{
Label: "Team ID",
Value: "T004",
},
{
Label: "User ID",
Value: "U004",
},
{
Label: "Last updated",
Value: "0001-01-01 00:00:00 Z",
},
{
Label: "Authorization level",
Value: "Workspace",
},
{
Label: "API Host",
Value: "https://example.com/api/",
},
{
Label: "Token status",
Value: "Valid",
},
},
Errors: []slackerror.Error{},
},
{
Subsections: []Section{
{
Label: "Team domain",
Value: "teamB",
},
{
Label: "Team ID",
Value: "E003",
},
{
Label: "User ID",
Value: "U003",
},
{
Label: "Last updated",
Value: "0001-01-01 00:00:00 Z",
},
{
Label: "Authorization level",
Value: "Organization",
},
{
Label: "Token status",
Value: "Valid",
},
},
Errors: []slackerror.Error{},
},
{
Subsections: []Section{
{
Label: "Team domain",
Value: "teamB",
},
{
Label: "Team ID",
Value: "T002",
},
{
Label: "User ID",
Value: "U002",
},
{
Label: "Last updated",
Value: "0001-01-01 00:00:00 Z",
},
{
Label: "Authorization level",
Value: "Workspace",
},
{
Label: "Token status",
Value: "Valid",
},
},
Errors: []slackerror.Error{},
},
},
expectedErrorSection: []slackerror.Error{},
},
}

for name := range tests {
for name, tt := range tests {
t.Run(name, func(t *testing.T) {
ctx := slackcontext.MockContext(t.Context())
clientsMock := shared.NewClientsMock()
clientsMock.Auth.On("Auths", mock.Anything).Return(tt.mockAuths, nil)
clientsMock.Auth.On("ResolveAPIHost", mock.Anything, mock.Anything, mock.Anything).Return("https://slack.com/api/", nil)
clientsMock.API.On("ValidateSession", mock.Anything, mock.Anything).Return(api.AuthSession{}, nil)
clientsMock.AddDefaultMocks()
clients := shared.NewClientFactory(clientsMock.MockClientFactory())
expected := Section{
Label: "Credentials",
Value: "your Slack authentication",
Subsections: []Section{},
Errors: []slackerror.Error{*slackerror.New(slackerror.ErrNotAuthed)},
Subsections: tt.expectedSections,
Errors: tt.expectedErrorSection,
}

section, err := checkCLICreds(ctx, clients)
Expand Down
36 changes: 12 additions & 24 deletions cmd/doctor/doctor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -178,40 +178,28 @@ func TestDoctorCommand(t *testing.T) {
Value: "",
Subsections: []Section{
{
Label: "Team domain",
Value: expectedCredentials.TeamDomain,
Subsections: []Section{},
Errors: []slackerror.Error{},
Label: "Team domain",
Value: expectedCredentials.TeamDomain,
},
{
Label: "Team ID",
Value: expectedCredentials.TeamID,
Subsections: []Section{},
Errors: []slackerror.Error{},
Label: "Team ID",
Value: expectedCredentials.TeamID,
},
{
Label: "User ID",
Value: expectedCredentials.UserID,
Subsections: []Section{},
Errors: []slackerror.Error{},
Label: "User ID",
Value: expectedCredentials.UserID,
},
{
Label: "Last updated",
Value: expectedUpdateTime,
Subsections: []Section{},
Errors: []slackerror.Error{},
Label: "Last updated",
Value: expectedUpdateTime,
},
{
Label: "Authorization level",
Value: "Workspace",
Subsections: []Section{},
Errors: []slackerror.Error{},
Label: "Authorization level",
Value: "Workspace",
},
{
Label: "Token status",
Value: "Valid",
Subsections: []Section{},
Errors: []slackerror.Error{},
Label: "Token status",
Value: "Valid",
},
},
Errors: []slackerror.Error{},
Expand Down
Loading