Slackからデモ環境のデータ作成リクエストを送る


環境

ruby 2.4
Rails 5.0
Redis 3.2
SlackAPI 2019年10月時点

gem

sidekiq 5.2.7
slack-notifier 2.3.2

背景

デモ環境の一つのアカウントをHPからの問い合わせや、営業の際に使用するアカウントとして使いまわしていたために次のような問題が発生していました。

アカウント使いまわし問題

・いつの間にかアカウントがロックされている(ログインを複数回失敗でロック)
・データが他の誰かの手によって作成・更新・削除されている

お客様毎にアカウントを発行してお渡しすれば上記問題は発生しないのですが、そこでもまた次のような問題がありました。

データ手作成問題

・デモデータを自動作成する仕組みがない
・アカウントデータだけ作成しても、サービスの機能が十分に伝わらない可能性がある
・アカウントデータ以外の初期データも手作成とか時間がかかり過ぎる
・デモデータ作成作業は、Salesチームが行うので複雑な作業・コマンドを実行する事はできない

デモ環境のデータなので、データ自動作成の仕組みを作って社内のメンバーなら誰でも発行できるようにしたいと考えました。

ちょうど会社の開発合宿があったので一日でサクッと作成しました。

仕組み

チャットツールとしてSlackを使用していたので、Slackからデータを自動作成する仕組みを作ろうと考えました。

1. SlackAPIアプリのbotにメンションメッセージを投げる
2. SlackAPIのEventに引っかかる
3. アプリのPostURLを叩く
4. データ作成のWorkerを実行
5. IncomingWebhooksでID/PASSを通知する
6. 特定のチャンネルにメッセージが送られる
7. ID/PASSが通知される

実装していく

1. Railsアプリ側にデモデータ作成用のエンドポイントを作成する

config/routes.rb
  resource :demo_data, only: :create

2. コントローラを実装する

app/controllers/demo_data_controller.rb
# frozen_string_literal: true

class DemoDataController < ActionController::Base
  def create
    if params[:challenge].present?
      render json: {challenge: params[:challenge]}
    else
      DemoData::CreateWorker.perform_async
    end
  end
end

この箇所ですが、

if params[:challenge].present?
      render json: {challenge: params[:challenge]}

SlackAPIアプリで Event Subscriptions を設定する際にURLの存在確認の為にレスポンスを確認をされるので必要になります。
詳しくは下記参照
https://api.slack.com/events/url_verification

3. SlackAPIでアプリを作成する

以下のURLから Create New App を押下
https://api.slack.com/apps

App Name を入力
Development Slack Workspace を選択
使用するWorkspaceを間違えないように選択して Create App を押下

4. 作成したSlackAPIアプリのBot Userを作成する

サイドメニューの Bot Users を押下
Add a Bot User を押下
任意の名前を入力して Add Bot User を押下

5. SlackAPIアプリのEvent Subscriptionsを設定する

サイドメニューの Event Subscriptions を押下
Enable EventsON に変更
Request URL に作成したエンドポイントを設定
Subscribe to bot eventsAdd Bot User Event から app_mention を選択
右下にある Save Changes を忘れずに押下

6. SlackAPIアプリのIncoming Webhooksを設定する

サイドメニューの Incoming Webhooks を押下
Activate Incoming WebhooksON に変更
Add New Webhook to Workspace を押下

別画面に飛ばされるので チャンネル を選択する
許可する を押下

7. 作成したアプリをWorspaceにインストールする

サイドメニューの Installed App を押下
Reinstall App を押下

別画面に飛ばされるので ワークスペース を選択する
Reinstall App を押下

8. Worker側からSlack通知する処理を実装する

app/workers/demo_data/create_worker.rb
# frozen_string_literal: true

class DemoData::CreateWorker
  include Sidekiq::Worker
  sidekiq_options queue: 'default'

  def perform
    # 好きなようにデモデータ作成処理
    send_slack
  end

  private

  def send_slack
    notifier = Slack::Notifier.new 'Webhook URL'

    begin
      notifier.post slack_params
    rescue Slack::Notifier::APIError => e
      Raven.capture_exception(e)
    end
  end

  def slack_params
    {
      attachments: [
        {
          title: "デモデータ作成が完了しました。",
          color: "#5F04B4",
          fields: [
              {
                  "title": "id",
                  "value": "ここにログインID"
              },
              {
                  "title": "password",
                  "value": "ここにログインPASSWORD"
              }
          ]
        }
      ]
    }
  end
end

この箇所の Webhook URL は、


  def send_slack
    notifier = Slack::Notifier.new 'Webhook URL'

作成したWebhook URLをコピーしてきて置き換えてください

9. 実際に使ってみる

アプリのボットユーザーに対してメンションを飛ばすだけです。

10. SlackAPIからのみPOSTリクエストを受け付ける

このままだとURLを知っていれば誰でもURLを叩けてしまうので
SlackAPIから送られてくるトークンを確認します。

app/controllers/demo_data_controller.rb
# frozen_string_literal: true

class DemoDataController < ActionController::Base
  def create
    raise "This action needs a verification token." if params[:token].nil? || params[:token] != ENV['TOKEN']

    if params[:challenge].present?
      render json: {challenge: params[:challenge]}
    else
      DemoData::CreateWorker.perform_async
    end
  end
end

この箇所の ENV['TOKEN'] は、

    raise "This action needs a verification token." if params[:token].nil? || params[:token] != ENV['TOKEN']

サイドメニューの Basic Information を押下
App CredentialsVerification Token です

以上です!