-
Notifications
You must be signed in to change notification settings - Fork 21
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: update slack notification by adding block functionality to temp…
…late (#370) * Enhance slack notifications to be able to use markdown formatting by adding message block functionality. Co-authored-by: sushmith <[email protected]>
- Loading branch information
1 parent
4437d32
commit aa29ea8
Showing
12 changed files
with
334 additions
and
33 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
# Notification configuration | ||
|
||
Templates of slack notifications sent through guardian can be configured. | ||
It is a Json string having list of blocks(Json). Developers can configure list of blocks according to the notification UI needed. | ||
It can be list of Texts, Sections, Buttons, inputs etc (Ref:https://api.slack.com/reference/block-kit/block-elements) | ||
|
||
|
||
## Examples: | ||
|
||
### Only Text: | ||
|
||
```json | ||
[{ | ||
"type": "section", | ||
"text": { | ||
"type": "mrkdwn", | ||
"text": "You have an appeal created by {{.requestor}} requesting access to {{.resource_name}} with role {{.role}}. Appeal ID: {{.appeal_id}}" | ||
} | ||
}] | ||
``` | ||
|
||
|
||
### Others (Sample approval notification): | ||
|
||
```json | ||
[ | ||
{ | ||
"type": "section", | ||
"text": { | ||
"type": "mrkdwn", | ||
"text": "You have an appeal created by {{.requestor}} requesting access to {{.resource_name}} with role {{.role}}. Appeal ID: {{.appeal_id}}" | ||
} | ||
}, | ||
{ | ||
"type": "section", | ||
"fields": [ | ||
{ | ||
"type": "mrkdwn", | ||
"text": "*Provider*\\n{{.provider_type}}" | ||
}, | ||
{ | ||
"type": "mrkdwn", | ||
"text": "*Resource Type:*\\n{{.resource_type}}" | ||
} | ||
] | ||
}, | ||
{ | ||
"type": "section", | ||
"fields": [ | ||
{ | ||
"type": "mrkdwn", | ||
"text": "*Resource:*\\n{{.resource_name}}" | ||
}, | ||
{ | ||
"type": "mrkdwn", | ||
"text": "*Account Id:*\\n{{.account_id}}" | ||
} | ||
] | ||
}, | ||
{ | ||
"type": "section", | ||
"fields": [ | ||
{ | ||
"type": "mrkdwn", | ||
"text": "*Role:*\\n{{.role}}" | ||
}, | ||
{ | ||
"type": "mrkdwn", | ||
"text": "*When:*\\n{{.created_at}}" | ||
} | ||
] | ||
}, | ||
{ | ||
"type": "section", | ||
"text": { | ||
"type": "mrkdwn", | ||
"text": "*Console link:*\nhttps://console.io/requests/{{.appeal_id}}" | ||
} | ||
}, | ||
{ | ||
"type": "input", | ||
"element": { | ||
"type": "plain_text_input", | ||
"placeholder": { | ||
"type": "plain_text", | ||
"text": "Approve/Reject reason? (optional)" | ||
}, | ||
"action_id": "reason" | ||
}, | ||
"label": { | ||
"type": "plain_text", | ||
"text": "Reason" | ||
} | ||
}, | ||
{ | ||
"type": "actions", | ||
"elements": [ | ||
{ | ||
"text": { | ||
"type": "plain_text", | ||
"emoji": true, | ||
"text": "Approve" | ||
}, | ||
"type": "button", | ||
"value": "approved", | ||
"style": "primary", | ||
"url": "https://console.io/appeal_action?action=approve&appeal_id={{.appeal_id}}&approval_step={{.approval_step}}&actor={{.actor}}" | ||
}, | ||
{ | ||
"text": { | ||
"type": "plain_text", | ||
"emoji": true, | ||
"text": "Reject" | ||
}, | ||
"type": "button", | ||
"value": "rejected", | ||
"style": "primary", | ||
"url": "https://console.io/appeal_action?action=reject&appeal_id={{.appeal_id}}&approval_step={{.approval_step}}&actor={{.actor}}" | ||
} | ||
] | ||
} | ||
] | ||
``` | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
package slack | ||
|
||
import ( | ||
"bytes" | ||
"errors" | ||
"io/ioutil" | ||
"net/http" | ||
"testing" | ||
|
||
"github.com/odpf/guardian/domain" | ||
"github.com/odpf/guardian/mocks" | ||
"github.com/stretchr/testify/mock" | ||
"github.com/stretchr/testify/suite" | ||
) | ||
|
||
type ClientTestSuite struct { | ||
suite.Suite | ||
mockHttpClient *mocks.HTTPClient | ||
accessToken string | ||
messages domain.NotificationMessages | ||
slackIDCache map[string]string | ||
notifier notifier | ||
} | ||
|
||
func (s *ClientTestSuite) setup() { | ||
s.mockHttpClient = new(mocks.HTTPClient) | ||
s.accessToken = "XXXXX-TOKEN-XXXXX" | ||
s.messages = domain.NotificationMessages{ | ||
AppealRejected: "[{\"type\":\"section\",\"text\":{\"type\":\"mrkdwn\",\"text\":\"Your appeal to {{.resource_name}} with role {{.role}} has been rejected\"}}]", | ||
} | ||
s.slackIDCache = map[string]string{} | ||
s.notifier = notifier{ | ||
accessToken: s.accessToken, | ||
slackIDCache: s.slackIDCache, | ||
Messages: s.messages, | ||
httpClient: s.mockHttpClient, | ||
defaultMessageFiles: defaultTemplates, | ||
} | ||
} | ||
|
||
func TestClient(t *testing.T) { | ||
suite.Run(t, new(ClientTestSuite)) | ||
} | ||
|
||
func (s *ClientTestSuite) TestNotify() { | ||
s.Run("should return error if slack id not found", func() { | ||
s.setup() | ||
|
||
slackAPIResponse := `{"ok":false,"error":"users_not_found"}` | ||
resp := &http.Response{StatusCode: 200, Body: ioutil.NopCloser(bytes.NewReader([]byte(slackAPIResponse)))} | ||
s.mockHttpClient.On("Do", mock.Anything).Return(resp, nil) | ||
expectedErrs := []error{errors.New("users_not_found"), errors.New("EOF")} | ||
|
||
actualErrs := s.notifier.Notify([]domain.Notification{ | ||
{ | ||
User: "[email protected]", | ||
Message: domain.NotificationMessage{ | ||
Type: domain.NotificationTypeAppealRejected, | ||
Variables: map[string]interface{}{ | ||
"ResourceName": "test-resource", | ||
}, | ||
}, | ||
}, | ||
}) | ||
|
||
s.Equal(expectedErrs, actualErrs) | ||
}) | ||
|
||
s.Run("should get default message template from file if not found in config", func() { | ||
s.setup() | ||
expectedContent, err := ioutil.ReadFile("templates/AppealApproved.json") | ||
content, err := getDefaultTemplate("AppealApproved", s.notifier.defaultMessageFiles) | ||
|
||
s.Equal(string(expectedContent), content) | ||
s.Equal(err, nil) | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
[ | ||
{ | ||
"type":"section", | ||
"text":{ | ||
"type":"mrkdwn", | ||
"text":"Your access to *{{.resource_name}}}* with role *{{.role}}* has been revoked" | ||
} | ||
} | ||
] |
Oops, something went wrong.