generalistからspecialistへ

一点集中化計画

Cookieの種類

Cookieは2種類ある

  • Session cookie. ブラウザを閉じた時点で破棄(Max-Age属性もExpires属性も指定されていない場合)クライアントはサーバに送信するCookieにセッションIDを載せてリクエストすることでセッションの維持ができるようになる
  • Persistent cookie. 長期。2週間とかいう単位。

Session 情報の保存:

  • ファイルに保存する
  • Cookie内に暗号化して持つ
  • MySQLなどのデータベースに保存する
  • memcachedなどのKVSに保存する

ブラウザでcookieを確認するには(chrome)

SSL / TSLの基本

自身のSSL / TSLについての理解を記録しておく。

当初の疑問:

SSLは誰が挙動を保証している?

  • SSL通信はクライアントアプリケーションからTCPにデータ送信する前に、SSLを噛ます

  • SSL ニアリーイコール TSL(SSLの次世代がTSL。どちらもセキュリティ掛ける規約)

  • 実際のSSL通信は「公開鍵+秘密鍵と共通鍵の併用」

  • プレマスタ・シークレット = 共通鍵のもとになるデータ

SSL通信の流れ:

  1. SSL掛かったサイトを訪問する
  2. サーバーがクライアントに公開鍵送る
  3. クライアントはサーバーから送られてきた公開鍵で、自分が持ってる共通鍵に鍵を掛けて、サーバーに送る
  4. サーバーは秘密鍵で鍵を開け、中に入っている共通鍵を取り出す
  5. これ以降、クライアントとサーバーは共通鍵でデータに鍵を掛け、通信し合う。

わざわざ共通鍵を使うのは、その方が処理が速いから。双方がやり取りする間、ヘッダー(どんな暗号方式を使うかとか)とデータ(内容)を送り合っている。

公開鍵+秘密鍵が必要になるタイミングは、セッションごと? 最初のSSLのサイトアクセス時は処理が遅くなってる?確認する方法あるかな。

とりあえず当初の疑問:

次の疑問:

  • サーバー証明書に含まれる認証局の署名が本物かどうかは、エンドユーザーはどうやって分かる?(秘密鍵で暗号化したデータがどうなっていたら本物かどうか、どうやって分かる?)

認証局は「複数」ある

  • クライアントのPCには最初から、ルート認証局の情報がいくつかinstallされている(今後も当分ルート認証局は同じであり続けるという事か)

  • PCに入っているルート認証局情報と、サイトにSSLアクセスした時に受信したサーバー証明書に入っているルート認証局情報を照らし合わせて、一致したらそのルート認証局情報は信頼できる

=そのルート認証局が保証しているサーバーも信頼できる

=そのサーバーが配布している公開鍵を使ってOK

  • よって疑問の=>サーバー証明書に含まれる認証局の署名が本物かどうかは、エンドユーザーはどうやって分かる?

は、「最初からPCに信頼できるルート認証局情報のリストが複数入っており、それと照合することで信頼できるかを判断する」 が答えとなる。

特に詰まった箇所:circleCI系

関連記事


  • 主に、localでは通るがcircleCIでは落ちる、という事がほとんどだった

今まで通っていたテストが、いきなり落ちる

  • cacheが関係している可能性。特にchromedriver周りがあやしい
  • chromedriverのcacheをコメントアウトしてテストに掛けると通る事がある。

CIのchromedriverは12時間制

  • input type="time"は、localでは以下のように見えているが、

f:id:sdk-quadra:20210113104743p:plain

  • CIのchromedriverではこのように見えている(AM、PMを指定する)
  • CIのchromedriverは12時間制

f:id:sdk-quadra:20210113104755p:plain

  • そういうわけで、以下のようなエラーになり、テストが通っていなかった。CIのデバグをする時はscreenshotを見ないと分からない(エラーメッセージだけでは分からない)

f:id:sdk-quadra:20210113104846p:plain

  • ちなみにこの場合、テストには以下のように最後にAMやPMを付けると通る
find("#time").set("#{hour}:#{minutes}AM")

特に詰まった箇所:テスト系

関連記事


factorybot

  • 以下のようなテストを書いている場合、it の中で@appnilになる
before(:context) do
    @workspace = FactoryBot.create(:workspace)
    @app = FactoryBot.create(:app, workspace_id: @workspace.id) 
    @channel = FactoryBot.create(:channel, workspace_id: @workspace.id)

    context "sessionを伴うtest" do
        let(:rspec_session) { { workspace_id: @workspace.id } }

        it "テキストメッセージを新規登録できる事" do
            p @app 
            p @channel
    end
end
  • @channelはちゃんと値が出力される
  • itの中で、@app = FactoryBot.create(:app, workspace_id: @workspace.id)を定義すると、その後で@appするとちゃんと値が出力される

before(:context)

  • この時、before(:context) doではなく、before doにすると、itの中で@appを出力できるようになる
  • どうやら、before(:context) do => context do => it doの順で動く時、context doを噛ませると @appnil になる という所までは分かった。だが、なぜそうなるのか分からない
  • let(:app) { FactoryBot.create(:app, workspace_id: @workspace.id) }context doに書くと、it do内でappで出力できた
  • しかしなぜ@channelはできて、@appができないのか両者のmodelなどの違いを見て行ったが、原因分からず。
  • 結局、原因は変数名(@app)だった。 予約されているらしい。他の名前にしたら出力された。すごい時間掛かった。

ログイン

  • omniauthなどはテストモードというのがあって、テストでのログイン方法を提供しているが、「sign in with slack」では提供されてない
  • rpsecでは、sessionが使えない為、ログイン後の挙動をテストできない
  • => 結局rspecでsessionを書き込めるようにrails_helper.rbを書き換えて実現した。これもかなり時間掛かった。

特に詰まった箇所:slack api系

関連記事


通信制

  • 同時に複数のapi通信をすると、その通信結果が保証されない場合がある。
  • 例えばメッセージを送信する場合は1秒に1回だと保証される。(公式
  • なので実装する場合、一気に通信しないように工夫する必要がある
  • この制限のドキュメントを後から見つけて、仕様を結構変更した。

メッセージに画像を含める

apiを使ってslackで画像を含めるメッセージを送るには、様々なメソッドがあるが、、

  • 画像は送れるがテキストは送れないメソッド
  • 画像は送れるしテキストも送れるが、テキストは一行しか送れないメソッド(改行を認識しない)

  • 画像URLをテキストとして記述すると展開されるが、画像に実体はなく(ダウンロードできない)引用っぽくなるメソッド

  • webhookを使っても送れるが、それだとchannelが新規にワークスペース上にできる度に、webhook APIで専用のURLを発行し、ユーザーに承認をクリックしてもらわないといけない。

  • テキストと画像は別で送るという方法もあるが、あまりスマートでは無い。

  • 画像専用で送るメソッドに、オプションでテキストも添付できるというのもある。が、それだと予約送信はできない。

  • なので、slack de stepでは最も基本的なメソッドchat.postMessageにオプションを付けて実装した。

f:id:sdk-quadra:20210112144854p:plain

  • 具体的なコード例は以下(curlコマンド)
    • {"type": "mrkdwn", "text": "これはテスト"}  のmrkdwnは、plain_textでもOK。ただしmrkdwnにしておけば、テキストのURLが受信したslackでURLリンクになる。もちろんmrkdwnなので記述がmarkdownに対応するという意味
$ curl -X POST 'https://slack.com/api/chat.postMessage' \
-d 'token=xoxb-xxxx-xxxx....' \
-d 'channel=U010B...' \
-d 'blocks=[{"block_id": "test_message", "type": "section","text": {"type": "mrkdwn", "text": "これはテスト"}}, {"type": "image", "title": {"type": "plain_text","text": "pitcure"}, "image_url": "https://画像URL", "block_id": "test_image","alt_text": "pitcure here"}]'

ログイン機能の注意点

  • 開発するアプリに、slackでのログイン機能を付けたくて、gemのomniauth-slackを使おうとするかも知れない。
  • 本家のslack api公式でもこの方法を紹介しているので、大丈夫だと思って使うと危険。このomniauth-slack、開発がかなり前に終わっている。
    • しかし、本家slack apiの方はどんどんバージョンアップしているので、omniauth-slackでは新しいメソッドが使えないという事が起こる。
    • その時によく保守されている方法(本家の「sign in with slack」など)を使うといい。

権限設定の注意点

  • slack apiの権限設定で、登録しても 「何かがおかしい」 とだけ表示されて登録できない時がある
  • 原因はchromeが日本語に訳しているから。英語表記にしたら登録できる場合がある。

f:id:sdk-quadra:20210112145046p:plain

slack app「公開」の意味

  • 現段階まで開発したアプリが、他人のslackではどう動くのかを確認したい時がある
  • しかし他のワークスペース(開発アカウント以外)で自分が作ったアプリを入れようとすると、「公開していないとできない」とエラーが出る
  • この「公開」の意味をslack app directoryに公開する = productionとしてリリースする、と思っていたが違った。「公開」には「身内にだけ(リンクを知っている人だけ)公開」と、slack app directoryに公開(slack 全userの目に触れる)の2種類あると、だいぶ経ってから分かった。

userのslack情報にアクセスする

  • slackのアプリを作る時、userのslack情報にアクセスしたい場合は「sign in with slack」を使えばできる。
  • 自分は当初、利用者に自分でslackのtokenを作って、そのtokenを送ってもらってアプリを使えるようにする、以下のようなUIを考えていた。

f:id:sdk-quadra:20210112145140p:plain

  • だが、userにsign in with slackで発行したURLを踏んでもらうと、そのuser専用のslack tokenが自動で発行される。なので、上記のようなUIの画面は必要なかった。apiの仕様が分かってくるほど、作るアプリの仕様も変更した。

権限更新時の注意点

  • 他のワークスペースに自分が作ったアプリがすでにinstallされている状態で、こちら側で権限スコープを変更すると
    • =>権限を追加する分には、再度連携のアナウンスがされて、権限が更新される
    • =>権限を削除する分には、反映されない。
    • 参考資料

ので、注意が必要。

ワークスペースへのアプリのインストール後に開発者がアプリのスコープを変更した場合、アプリ管理者が新しいスコープを確認できるよう、メンバーはアプリを再度リクエストする必要があります。アプリ管理者がアプリの新しいスコープを制限した場合、メンバーはそのアプリの既存のバージョンを引き続き使用できますが、更新バージョンのインストールや使用はできません

  • では、すでにinstallしているユーザーに対して権限を削除(制限)したい場合はどうするのか。
  • =>一旦アプリをuninstall後、再度installしてもらうしかなさそう。(注意:これをするとtokenが再発行される = 以前のtokenは無効化する

botを動かす時の注意点

  • botとuserという2つの存在をしっかり押さえておく必要がある
  • userとは、普通にuserの事。slack上にいる同僚のAさんとかがそう。Aさんはslackをやってて、他人からメッセージが来たら「アラート」が鳴って、自分が所属しているチャンネルにBさんが参加してきたら、「Bさんが参加しました」とメッセージが表示される。要するに、userはslack上で発生する「イベント」を自動で検知する
  • しかし、これがbotの場合はそうでなくなる
  • 例えば、ワークスペース上に新しいchannelができて、そこにuserが参加したとすると、そのchannelにどのuserが所属しているかどうかをbotが検知するには、botがそのchannelに所属してないといけない
  • botはdefaultでチャンネルに所属していない。
  • もし、userが新規でチャンネルをslack上で作り、そのチャンネルで起こったイベントをbotで検知したければ、そのチャンネルにbotを仕込む必要がある
  • もし、新しくチャンネルが作られて、同時にそのチャンネルに参加したuserをbotで把握したければ、userがチャンネルに参加するより先に、botがチャンネルに入り込まないといけないので、タイミングが重要

不正確な説明内容

  • slack自身の説明が事実と違う場合がある。
  • 以下はmacのslackアプリで、slackのチャンネルをアーカイブしようとした時に表示される説明である。
  • チャンネルを復元する事ができるが、メンバーは削除されたままだと書かれてある。

f:id:sdk-quadra:20210118173355p:plain

  • しかしチャンネルを復元すると、きっちり5分後にメンバーも復活する。デバグにかなりの時間が掛かった。
  • というように、slackのapiには事実と違う内容が書かれている場合があるので注意が必要。
  • 多分ドキュメントの更新が追いついていないのでは

特に詰まった箇所:環境系

関連記事


JSON.parseエラー 767

  • macで開発したコードを、windowsで動かした時に起こった事象
  • JSON.parseエラー 767が出る
  • ネット上に資料があまりなく、苦労する
  • jsonファイルの破損ではない。
  • 環境周りを見直すが問題はない。
  • 結局、windowsでは、curlで文字列をシングルクォートで囲ってはいけないということが分かる。ダブルクォートにするとエラーが消えた。1日掛かった。