Skip to content

Commit

Permalink
update slack oauth path and standardize slack req/res naming
Browse files Browse the repository at this point in the history
In anticipation of future additional Slack workflows other than
message posting and oauth, like listening to incoming events.
  • Loading branch information
yasunariw committed Dec 29, 2020
1 parent b4cfce5 commit cf9b42f
Show file tree
Hide file tree
Showing 8 changed files with 17 additions and 17 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,14 @@ If you are preparing the app for distribution, you also need to enable automatic

You should...

1. In your Slack app dashboard, click on "OAuth & Permissions" in the sidebar. Set the *Redirect URL* to be `<server_domain>/slack`, and ensure your bot has a *Bot Token Scope* of `chat:write`.
1. In your Slack app dashboard, click on "OAuth & Permissions" in the sidebar. Set the *Redirect URL* to be `<server_domain>/slack/oauth`, and ensure your bot has a *Bot Token Scope* of `chat:write`.
1. You can optionally provide a value for `slack_oauth_state` in your secrets file to [avoid forgery attacks](https://tools.ietf.org/html/rfc6749#section-4.1.1) during the OAuth exchange.
1. Launch the server with the `run` command. Make sure it's reachable externally from same the `server_domain` you used for the GitHub Payload URL. The bot server will listen on `/slack` for incoming OAuth requests.
1. Launch the server with the `run` command. Make sure it's reachable externally from same the `server_domain` you used for the GitHub Payload URL. The bot server will listen on `/slack/oauth` for incoming OAuth requests.
1. When the server completes an OAuth exchange and doesn't have an access token defined yet, the secrets file on the server will be regenerated to include a `slack_access_token` field.

Your users should...

1. Go to the following address, replacing the appropriate values (the `state` argument is only needed if you set `slack_oauth_state` in the previous step). `https://slack.com/oauth/v2/authorize?scope=chat:write&client_id=<slack_client_id>&redirect_uri=<server_domain>/slack&state=<slack_oauth_state>`
1. Go to the following address, replacing the appropriate values (the `state` argument is only needed if you set `slack_oauth_state` in the previous step). `https://slack.com/oauth/v2/authorize?scope=chat:write&client_id=<slack_client_id>&redirect_uri=<server_domain>/slack/oauth&state=<slack_oauth_state>`
1. A page should open asking for permission to install the bot to the workspace. When prompted, click "Allow".
1. Add the bot to all Slack channels the user wants to send notifications to.

Expand Down
2 changes: 1 addition & 1 deletion lib/action.ml
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ module Action (Github_api : Api.Github) (Slack_api : Api.Slack) = struct
| _ -> Lwt.return []

let send_notifications (ctx : Context.t) notifications =
let notify (msg : Slack_t.message) =
let notify (msg : Slack_t.post_message_req) =
match%lwt Slack_api.send_notification ~ctx ~msg with
| Ok () -> Lwt.return_unit
| Error e -> action_error e
Expand Down
2 changes: 1 addition & 1 deletion lib/api.ml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ module type Github = sig
end

module type Slack = sig
val send_notification : ctx:Context.t -> msg:message -> (unit, string) Result.t Lwt.t
val send_notification : ctx:Context.t -> msg:post_message_req -> (unit, string) Result.t Lwt.t

val update_access_token_of_context : ctx:Context.t -> code:string -> (unit, string) Result.t Lwt.t
end
6 changes: 3 additions & 3 deletions lib/api_local.ml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ end

module Slack : Api.Slack = struct
let send_notification ~ctx:_ ~msg =
let json = msg |> Slack_j.string_of_message |> Yojson.Basic.from_string |> Yojson.Basic.pretty_to_string in
let json = msg |> Slack_j.string_of_post_message_req |> Yojson.Basic.from_string |> Yojson.Basic.pretty_to_string in
Stdio.printf "will notify #%s\n" msg.channel;
Stdio.printf "%s\n" json;
Lwt.return @@ Ok ()
Expand All @@ -35,7 +35,7 @@ end
module Slack_simple : Api.Slack = struct
let log = Log.from "slack"

let send_notification ~ctx:_ ~(msg : Slack_t.message) =
let send_notification ~ctx:_ ~(msg : Slack_t.post_message_req) =
log#info "will notify %s%s" msg.channel
( match msg.Slack_t.text with
| None -> ""
Expand All @@ -50,7 +50,7 @@ module Slack_json : Api.Slack = struct
let log = Log.from "slack"

let send_notification ~ctx:_ ~msg =
let json = Slack_j.string_of_message msg in
let json = Slack_j.string_of_post_message_req msg in
log#info "will notify %s" msg.channel;
let url = Uri.of_string "https://api.slack.com/docs/messages/builder" in
let url = Uri.add_query_param url ("msg", [ json ]) in
Expand Down
6 changes: 3 additions & 3 deletions lib/api_remote.ml
Original file line number Diff line number Diff line change
Expand Up @@ -56,13 +56,13 @@ module Slack : Api.Slack = struct
| None -> Lwt.return @@ fmt_error "failed to retrieve Slack access token"
| Some access_token ->
let url = "https://slack.com/api/chat.postMessage" in
let data = Slack_j.string_of_message msg in
let data = Slack_j.string_of_post_message_req msg in
let headers = [ Printf.sprintf "Authorization: Bearer %s" access_token ] in
let body = `Raw ("application/json", data) in
log#info "sending to %s : %s" msg.channel data;
( match%lwt http_request ~body ~headers `POST url with
| Ok s ->
let res = Slack_j.message_response_of_string s in
let res = Slack_j.post_message_res_of_string s in
if res.ok then Lwt.return @@ Ok ()
else (
let msg = Option.value ~default:"an unknown error occurred" res.error in
Expand All @@ -81,7 +81,7 @@ module Slack : Api.Slack = struct
match%lwt Common.http_request ~body ~headers `POST "https://slack.com/api/oauth.v2.access" with
| Error e -> Lwt.return @@ Error e
| Ok data ->
let response = Slack_j.oauth_access_response_of_string data in
let response = Slack_j.oauth_access_res_of_string data in
( match response.access_token, response.error with
| Some access_token, _ -> Lwt.return @@ Ok access_token
| None, Some e -> Lwt.return @@ Error e
Expand Down
6 changes: 3 additions & 3 deletions lib/slack.atd
Original file line number Diff line number Diff line change
Expand Up @@ -53,21 +53,21 @@ type message_block = [
| Divider of message_divider_block
] <json adapter.ocaml="Atdgen_runtime.Json_adapter.Type_field">

type message = {
type post_message_req = {
channel: string;
?text: string nullable;
?attachments: message_attachment list nullable;
?blocks: message_block list nullable;
}

(* expected payload when exchanging oauth code for access token *)
type oauth_access_response = {
type oauth_access_res = {
ok: bool;
?access_token: string option;
?error: string option;
}

type message_response = {
type post_message_res = {
ok: bool;
?channel: string option;
?error: string option;
Expand Down
2 changes: 1 addition & 1 deletion src/notabot.ml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ let check_gh_action file json config secrets state =
let check_slack_action file secrets =
let data = Stdio.In_channel.read_all file in
let ctx = Context.make ~secrets_filepath:secrets () in
match Slack_j.message_of_string data with
match Slack_j.post_message_req_of_string data with
| exception exn -> log#error ~exn "unable to parse notification"
| msg ->
match Context.refresh_secrets ctx with
Expand Down
4 changes: 2 additions & 2 deletions src/request_handler.ml
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ let setup_http ~ctx ~signature ~port ~ip =
log#info "%s" request.body;
let%lwt () = Action.process_github_notification ctx request.headers request.body in
ret (Lwt.return "ok")
| _, [ "slack" ] ->
log#info "%s" request.body;
| _, [ "slack"; "oauth" ] ->
log#info "slack oauth authorization request received";
let%lwt () = Action.process_slack_oauth ctx request.args in
ret (Lwt.return "ok")
| _, _ ->
Expand Down

0 comments on commit cf9b42f

Please sign in to comment.