Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ListTeams and TeamAccess{Granted,Revoked}Events and fix missing enterprise ID #1119

Merged
merged 4 commits into from Dec 16, 2022
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
34 changes: 34 additions & 0 deletions auth.go
Expand Up @@ -38,3 +38,37 @@ func (api *Client) SendAuthRevokeContext(ctx context.Context, token string) (*Au

return api.authRequest(ctx, "auth.revoke", values)
}

type listTeamsResponse struct {
Teams []Team `json:"teams"`
SlackResponse
}

type ListTeamsParameters struct {
Limit int
Cursor string
}

// ListTeams returns all workspaces a token can access.
kanata2 marked this conversation as resolved.
Show resolved Hide resolved
// More info: https://api.slack.com/methods/admin.teams.list
func (api *Client) ListTeams(params ListTeamsParameters) ([]Team, string, error) {
return api.ListTeamsContext(context.Background(), params)
}

// ListTeams returns all workspaces a token can access with a custom context.
func (api *Client) ListTeamsContext(ctx context.Context, params ListTeamsParameters) ([]Team, string, error) {
values := url.Values{
"token": {api.token},
}
if params.Cursor != "" {
values.Add("cursor", params.Cursor)
}

response := &listTeamsResponse{}
err := api.postMethod(ctx, "auth.teams.list", values, response)
if err != nil {
return nil, "", err
}

return response.Teams, response.ResponseMetadata.Cursor, response.Err()
}
51 changes: 51 additions & 0 deletions auth_test.go
@@ -0,0 +1,51 @@
package slack

import (
"net/http"
"testing"

"github.com/stretchr/testify/assert"
)

func getTeamList(rw http.ResponseWriter, r *http.Request) {
rw.Header().Set("Content-Type", "application/json")
response := []byte(`{
"ok": true,
"teams": [
{
"name": "Shinichi's workspace",
"id": "T12345678"
},
{
"name": "Migi's workspace",
"id": "T12345679"
}
],
"response_metadata": {
"next_cursor": "dXNlcl9pZDo5MTQyOTI5Mzkz"
}
}`)
rw.Write(response)
}

func TestListTeams(t *testing.T) {
http.HandleFunc("/auth.teams.list", getTeamList)

once.Do(startServer)
api := New("testing-token", OptionAPIURL("http://"+serverAddr+"/"))

teams, cursor, err := api.ListTeams(ListTeamsParameters{})
if err != nil {
t.Errorf("Unexpected error: %s", err)
return
}

assert.Len(t, teams, 2)
assert.Equal(t, "T12345678", teams[0].ID)
assert.Equal(t, "Shinichi's workspace", teams[0].Name)

assert.Equal(t, "T12345679", teams[1].ID)
assert.Equal(t, "Migi's workspace", teams[1].Name)

assert.Equal(t, "dXNlcl9pZDo5MTQyOTI5Mzkz", cursor)
}
19 changes: 14 additions & 5 deletions conversation.go
Expand Up @@ -342,17 +342,26 @@ func (api *Client) CloseConversationContext(ctx context.Context, channelID strin
return response.NoOp, response.AlreadyClosed, response.Err()
}

type CreateConversationParams struct {
ChannelName string
IsPrivate bool
TeamID string
}

// CreateConversation initiates a public or private channel-based conversation
func (api *Client) CreateConversation(channelName string, isPrivate bool) (*Channel, error) {
return api.CreateConversationContext(context.Background(), channelName, isPrivate)
func (api *Client) CreateConversation(params CreateConversationParams) (*Channel, error) {
return api.CreateConversationContext(context.Background(), params)
}

// CreateConversationContext initiates a public or private channel-based conversation with a custom context
func (api *Client) CreateConversationContext(ctx context.Context, channelName string, isPrivate bool) (*Channel, error) {
func (api *Client) CreateConversationContext(ctx context.Context, params CreateConversationParams) (*Channel, error) {
values := url.Values{
"token": {api.token},
"name": {channelName},
"is_private": {strconv.FormatBool(isPrivate)},
"name": {params.ChannelName},
"is_private": {strconv.FormatBool(params.IsPrivate)},
}
if params.TeamID != "" {
values.Set("team_id", params.TeamID)
}
response, err := api.channelRequest(ctx, "conversations.create", values)
if err != nil {
Expand Down
2 changes: 1 addition & 1 deletion conversation_test.go
Expand Up @@ -385,7 +385,7 @@ func TestCreateConversation(t *testing.T) {
http.HandleFunc("/conversations.create", okChannelJsonHandler)
once.Do(startServer)
api := New("testing-token", OptionAPIURL("http://"+serverAddr+"/"))
channel, err := api.CreateConversation("CXXXXXXXX", false)
channel, err := api.CreateConversation(CreateConversationParams{ChannelName: "CXXXXXXXX"})
if err != nil {
t.Errorf("Unexpected error: %s", err)
return
Expand Down
2 changes: 1 addition & 1 deletion examples/pins/pins.go
Expand Up @@ -43,7 +43,7 @@ func main() {
postAsUserID = authTest.UserID

// Create a temporary channel
channel, err := api.CreateConversation(channelName, false)
channel, err := api.CreateConversation(slack.CreateConversationParams{ChannelName: channelName})

if err != nil {
// If the channel exists, that means we just need to unarchive it
Expand Down
18 changes: 18 additions & 0 deletions slackevents/inner_events.go
Expand Up @@ -524,6 +524,18 @@ func (e MessageEvent) IsEdited() bool {
e.Message.Edited != nil
}

// TeamAccessGrantedEvent is sent if access to teams was granted for your org-wide app.
type TeamAccessGrantedEvent struct {
Type string `json:"type"`
TeamIDs []string `json:"team_ids"`
}

// TeamAccessRevokedEvent is sent if access to teams was revoked for your org-wide app.
type TeamAccessRevokedEvent struct {
Type string `json:"type"`
TeamIDs []string `json:"team_ids"`
}

type EventsAPIType string

const (
Expand Down Expand Up @@ -599,6 +611,10 @@ const (
MessageMetadataUpdated = EventsAPIType("message_metadata_updated")
// MessageMetadataPosted A message with metadata was deleted
MessageMetadataDeleted = EventsAPIType("message_metadata_deleted")
// TeamAccessGranted is sent if access to teams was granted for your org-wide app.
TeamAccessGranted = EventsAPIType("team_access_granted")
// TeamAccessrevoked is sent if access to teams was revoked for your org-wide app.
TeamAccessrevoked = EventsAPIType("team_access_revoked")
)

// EventsAPIInnerEventMapping maps INNER Event API events to their corresponding struct
Expand Down Expand Up @@ -641,4 +657,6 @@ var EventsAPIInnerEventMapping = map[EventsAPIType]interface{}{
MessageMetadataPosted: MessageMetadataPostedEvent{},
MessageMetadataUpdated: MessageMetadataUpdatedEvent{},
MessageMetadataDeleted: MessageMetadataDeletedEvent{},
TeamAccessGranted: TeamAccessGrantedEvent{},
TeamAccessrevoked: TeamAccessRevokedEvent{},
}
1 change: 1 addition & 0 deletions slackevents/outer_events.go
Expand Up @@ -35,6 +35,7 @@ type EventsAPICallbackEvent struct {
Token string `json:"token"`
TeamID string `json:"team_id"`
APIAppID string `json:"api_app_id"`
EnterpriseID string `json:"enterprise_id"`
InnerEvent *json.RawMessage `json:"event"`
AuthedUsers []string `json:"authed_users"`
AuthedTeams []string `json:"authed_teams"`
Expand Down
8 changes: 4 additions & 4 deletions slackevents/parsers.go
Expand Up @@ -102,7 +102,7 @@ func parseInnerEvent(e *EventsAPICallbackEvent) (EventsAPIEvent, error) {
e.TeamID,
"unmarshalling_error",
e.APIAppID,
"",
e.EnterpriseID,
&slack.UnmarshallingErrorEvent{ErrorObj: err},
EventsAPIInnerEvent{},
}, err
Expand All @@ -114,7 +114,7 @@ func parseInnerEvent(e *EventsAPICallbackEvent) (EventsAPIEvent, error) {
e.TeamID,
iE.Type,
e.APIAppID,
"",
e.EnterpriseID,
nil,
EventsAPIInnerEvent{},
}, fmt.Errorf("Inner Event does not exist! %s", iE.Type)
Expand All @@ -128,7 +128,7 @@ func parseInnerEvent(e *EventsAPICallbackEvent) (EventsAPIEvent, error) {
e.TeamID,
"unmarshalling_error",
e.APIAppID,
"",
e.EnterpriseID,
&slack.UnmarshallingErrorEvent{ErrorObj: err},
EventsAPIInnerEvent{},
}, err
Expand All @@ -138,7 +138,7 @@ func parseInnerEvent(e *EventsAPICallbackEvent) (EventsAPIEvent, error) {
e.TeamID,
e.Type,
e.APIAppID,
"",
e.EnterpriseID,
e,
EventsAPIInnerEvent{iE.Type, recvEvent},
}, nil
Expand Down
2 changes: 1 addition & 1 deletion slacktest/handlers_test.go
Expand Up @@ -37,7 +37,7 @@ func TestServerCreateConversationHandler(t *testing.T) {
go s.Start()

client := slack.New("ABCDEFG", slack.OptionAPIURL(s.GetAPIURL()))
conversation, err := client.CreateConversation("test", false)
conversation, err := client.CreateConversation(slack.CreateConversationParams{ChannelName: "test"})
assert.NoError(t, err)
assert.Equal(t, "C0EAQDV4Z", conversation.ID)
assert.Equal(t, "U023BECGF", conversation.Creator)
Expand Down