今日のつちや

岐阜の田舎に住むエンジニアの日記です

Slack用の絵文字ジェネレーターを作った

f:id:corocn:20190212201948p:plain:w128

Slack用の絵文字ジェネレーターを作りました。

特徴としては、リアルタイムに表示を確認しながら絵文字を作ることができるところ。

slackemojigen.com

絵文字ジェネレーターなんてたくさんあるじゃーん!と言われればそれまでなんですが、普段使用している絵文字ジェネレーターが毎回生成ボタンを押さなきゃいけないので、さくさく複数フォントの確認できるやつが欲しかったので作りました。あとはVue.js + TypeScriptの練習として連休で作れるものとして採用。

ためしがき に多大なる影響を受けています。

デモ動画

こだわりとか

  • リアルタイムにフォントを見比べられる
  • Slackで表示した時のサイズ感を確認できる
  • 9段階 font-weight に対応(フォントによって未対応の太さはある)
  • プリセットで使ってる4色はSlackロゴの4色から採用

技術スタック

Nuxt.jsが公式にTypeScript対応したので、ほぼTypeScriptで書いてます。 最近副業でTypeScript + Express でサーバーサイド開発してるけど、TypeScriptはいいぞ。Expressも良いぞ。この辺の知見は別途記事を書きますね。

サーバーサイド不要なのでSPAとしてNetlifyでホスティングすることにしました。 ドメインがせっかくAmazon Route53にあるので、Amplify Consoleを使ってもいいかと思ったけど、また次回にします。

仕組み

仕組みは簡単で、WebFontを使ってHTML5 Canvasに描画してるだけです。ダウンロードボタンを付けたけど、実は右クリックメニューからもダウンロードできます。

FontはWebFontLoaderとNuxt用のプラグインを使っています。対応したいfont-weightは全部読み込ませています。

  webfontloader: {
    timeout: 30000,
    google: {
      families: [
        'M+PLUS+1p:100,300,400,500,700,800,900',
        'M+PLUS+Rounded+1c:100,300,400,500,700,800,900',
        'Noto+Sans+JP:100,300,400,500,700,900',
        'Noto+Sans+SC:100,300,400,500,700,900',
        'Noto+Sans+TC:100,300,400,500,700,900',
        'Noto+Serif+JP:200,300,400,500,600,700,900',
        'Noto+Serif+SC:200,300,400,500,600,700,900',
        'Noto+Serif+TC:200,300,400,500,600,700,900',
        'Kosugi',
        'Kosugi+Maru',
        'Sawarabi+Gothic',
        'Sawarabi+Mincho',
      ]
    }
  },

WebFontの読み込み完了後に描画処理を走らせる必要があります。WebFontLoaderでも読み込み完了イベントをキャッチすることはできますが、FontFaceObserverのほうが使いやすかった。

 const font = new FontFaceObserver("M PLUS Rounded 1c", { weight: 900 })
 font.load("えも\nじ").then(() => {
     // ここで描画する
 })

自前のdrawメソッドの中に上記のような処理を入れています。 font-family, font-weight, これから描画する文字を指定して、ロード完了を待って描画。

今後

コード整理してGitHubに公開する予定。(現状だいぶ見せられない汚さw) 色んなフォントに対応できるといいけど大変そうなので、みんな使ってくれるようなら頑張ります。

フィードバック頂けると嬉しいです。

twitter.com

Thanks!!

公開前に見てもらってありがとう〜 @nabettu @girigiribauer

DIYの電動昇降デスク買ったら捗った

リモートワークしてるエンジニアなので、座りっぱなし作業環境を改善したく、DIYタイプの電動昇降デスクを購入してみた。

今回買ったのは FlexiSpot E3B で 5万円ぐらい。電動昇降デスクの中ではコスパがいいほう。

購入ツイートしたら、興味ある人が多かったようなので、ちゃんとレビューしてみた。

導入前の机

導入前はIKEAで購入した机を使ってた。雑だけどヤスリがけして、オイル塗ったんで愛着がある。

f:id:corocn:20190126120741j:plain
電動昇降デスク導入前

良かったところ

  • ある程度の幅・奥行きが確保されている(155x75)
  • 木製の天板がいい
  • 高価すぎない(組み立てに電動ドライバーが必要なので、合計25000円ぐらい)

微妙だったところ

  • 天板に対して脚が脆弱で不安定すぎる
  • 私の身長(160cm)に対して天板の位置(73cm)が高すぎる

不安定さは使っているうちに気にならなくなった。天板の高さは椅子を高くすると、足が地面に接地しないので、姿勢が悪くなる原因になってた。肩こりや腰痛にも繋がるので良くない。

最適な机の高さ

最適な机の高さは以下のサイトから計算できる。

身長160cmの私の場合、天板の高さの最適値は

  • 座った状態: 63cm
  • 立った状態: 93cm

今の机と10cmも違う。肩こりや腰痛を防止するためには、適正な高さの机を使うことが大事。

調整できるタイプの脚すれば良いんだけど、ずっと座っている状態がよくないし、スタンディングでも作業したいので、電動昇降デスクを試してみることにした。

電動昇降デスクの選定

今回のデスクを選んだときの基準は

  • 天板のサイズが今より広い(155x75 以上)
  • 高さ60cmまで下げられる
  • 送料込み5万円前後
  • モニターアームが付けれる
  • 安定している
  • 木製がいい

雑に調べると20万ぐらいのデスクがヒットして、膝から崩れ落ちそうになる。ちゃんと調べると5万前後のデスクがそこそこ見つかる。

身長が高ければこのあたりでもいいかも。天板込み。

色々調べた結果、今の天板も使い回せるし、今後天板を買い換えるという選択が取れるFlexiSpot E3B(脚のみ) にした。天板新しくすると2万ほどかかるのでちょっと予算オーバー。現在使用中のIKEA天板を流用した。

天板の選定

私の場合はIKEA天板を使いまわしたけど、集成材のオーダーカット注文するという手がある。

木材通販のマルトクショップ

材質とサイズにもよるが、155x75ぐらいの天板であれば、集成材なら1万〜、集成材+表面塗装で2万〜、無垢材であれば4万〜 ぐらい。地味に塗装で値段があがるので自分でやるのも面白いかも。

材質によっては柔らかく、経年で湾曲する可能性があるので、裏面に補強が入っていると良い。IKEA天板の裏には補強材が入っている(組み立て作業中の写真参考)

余談だけど、IKEAのGERTONは バーチ(カバ)と呼ばれる材質を使っている。この素材がめちゃんこ硬くて、しょぼい電動ドリル/ドライバーだと天板の取り付けが運ゲー*2 になるので注意が必要。もしGERTONを検討する場合は、GERTONでDIYしてる人が沢山いるので、事前に調べたほうがいい。

FlexiSpotの組み立て

まず重すぎるので、玄関で開封してパーツごとに部屋に運び込んだ

できれば2人以上で組み立てたほうがいい

f:id:corocn:20190126121510j:plain
玄関から動かせないFlexiSpotくん

FlexiSpot 30kgぐらいあるので天板20kgと合わせて50kg。床が抜けるんじゃないかと社内Slackで心配されたけど、人間の体重相当なので問題なさそう。

重すぎってレビューがついてるのを見たけど、これぐらい重くないと不安定になるので、安心。

f:id:corocn:20190126122220j:plain
組み立て作業中

f:id:corocn:20190126122303j:plain
天板に乗せた図

f:id:corocn:20190126122659j:plain
完成。いいかんじ。

f:id:corocn:20190126122731j:plain
昇降コントローラー

天板が硬すぎてネジが全部入らなかったけど、いまのところ安定しているのでヨシ。コントローラーの写真を見てもらうと分かるけど、隙間が空いてる。

ネジ数が多いので、組み立てには電動ドライバーを用意しておくといい。 借りるのも手ですね。

f:id:corocn:20190126123229j:plain
PCを置いたの図

ケーブルが見苦しい。モニタはディスプレイアームを使って、可能な限り下げるようにしている。正面を向いたときの目線が、ディスプレイの上端にくるぐらいがちょうど良い。

かっこいい!

使ってみた感想

非常に満足度が高い。買ってよかった。

使い始めた1週間は、毎日2時間程度スタンディングにしていたけど、最近は勤務中はずっとスタンディングにしている。8時間立ちっぱなしは筋肉痛になるけど、もう慣れた。以下のような効果を感じている。

  • 集中力が上がった
  • 昼食後の眠気がなくなった
  • 脚がムキムキに
  • たまに姿勢を切り替えることで気分転換になる
  • 高さを調整できるので座った状態の姿勢も改善した

デスクワークで運動不足になりがちな人は、ぜひ検討してみるといい。 特にリモートワーカーにはオススメしたい。姿勢もよくなる。

次は自作キーボードを作るぞ!

FlexiSpot 電動式スタンディングデスク 高さ調節スタンドアップワークテーブル学習机勉強机 ブラックE3B

*1:実際の価格は13000円だが、送料が7000円ぐらいする。

*2:場所によってすんなりネジが入ったり入らなかったり

2018年を振り返りと2019年の目標を少し

2018年の振り返りするぞ! まずは今年立てた目標を見ていく。

  • 新しい言語を学ぶ(Kotlinあたり)
  • 本を書きたい(技術書典に出したい)
  • 結婚したいです
  • 前のめりでやっていく

新しい言語を学ぶ

Kotlin、Go、Typescriptを書く機会があった。 普段は動的型付け言語ばかり触っていたので、静的型付け言語に触れる機会が持てたので良かった。

CodeRetreat と呼ばれるペアプロのイベントに参加して、PythonやJuliaにも触れることができた。

言語ではないが、認証認可技術(OIDC, FIDO2)を深掘りしたり、コンテナ技術(主にKubernetes)を学ぶこともできた。仕事ではAWSにべったりなので、プライベートでGCPを触れたのも良かった。

本を書きたい

技術書典4・5と出展することができ、大変ありがたいことに、出版社からお声がけいただき、商業誌の出版もできた。かなりのプライベートの時間を執筆に費やしたと思う。 出版自体はじめてで、全部一人で準備したので相当大変だったし緊張したが、良い経験になった。

結婚した

結婚することができた。妻に感謝。みんなに感謝。 毎週片道2時間かけて会いにいってたので、残業がなく、土日はちゃんと休む文化のホワイトな会社なので良かった。 そんな働き方が当たり前になる社会にしていきたい。

前のめりでやった

すごいアバウトな目標で反省はしているが、色々やった

  • Vue.js Night Nagoyaのイベント開催
  • Auth0 Ambassador への就任と発信活動
  • エンジニア採用系イベントへの登壇
  • ID系のイベント参加

東京1往復で2万飛ぶんだけど、結構な頻度で東京に行ったと思う。

その他やったこと

カレー

カレー作りに嵌って毎週作っていた。最近はカレーにとどまらずに、スパイス系の料理が作りたいなと思って火鍋を作ってみたり、色々作っている。調理師免許欲しい。

引っ越し

結婚したので引っ越した。家電を買い揃えた。食洗機と洗濯乾燥機とルンバのおかげでQoLが爆上げした。

2019年

目標は年が明けたらまとめる。ぼんやり今考えていること。

  • 転職
  • 開業(副業)してみる
  • 新しい言語を学ぶ
  • リモートワークに関する情報発信をする
  • リモートの勉強会を立ち上げる
  • マネジメントの技術を学ぶ
  • 子供がほしい

2019年は、個人のライフスタイルにあった働き方ができる活動に沢山コミットしていきたいと思う。このような気持ちが生まれたのは、結婚によってライフスタイルが大きく変わったのが発火点だが、今までに見てきた職場環境やトラウマが燃料になっている。

ということで、お仕事のお誘いやリモートワークやエンジニア採用関連の登壇依頼お待ちしております〜!来年も @corocn よろしくお願いします!

ALB + Lambda + Ruby に認証機能を付けてみる

こんにちは、@corocn です。 この記事は Misoca+弥生 Advent Calendar 2018 3日目の記事です。 最近は認証認可やFIDO2.0周りを中心に遊んでます。

さてAWS re:Invent 2018では次の新機能が発表されました。

これを組み合わせると、ALBのエンドポイントを叩くことでRubyで記述されたLambdaを実行することができます。 既に沢山の方が試して、記事をあげていますね。

さらに半年ほど前に次のような機能の発表がありました。

ALBがOpenID Connectに対応したとの話です。ALBに簡単に認証機能を組み込むことができます。

これらを組み合わせて、セキュアなRubyの実行環境を作ろうというのが今回のネタです。

LambdaでRubyを動かす

まずはLambdaをRubyで記述します。ランタイム選択時にRuby 2.5を選択するだけです。 デフォルトのコードは次のようになっています。

require 'json'

def lambda_handler(event:, context:)
    # TODO implement
    { statusCode: 200, body: JSON.generate('Hello from Lambda!') }
end

ALBからアクセスする場合、この返り値では不十分なので修正します。

require 'json'

def lambda_handler(event:, context:)
{
    statusCode: 200,
    statusDescription: '200 OK',
    isBase64Encoded: false,
    headers: {
        'Content-Type': 'text/html; charset=utf-8'
    },
    body: 'Hello from Lambda!',
}
end

以下の記事を参考にしました。

ALBとLambdaを連携する

ALBとの連携はLambdaのトリガーの追加でも良いし、EC2のダッシュボードからALBを作成して、ターゲットに追加しても良いです。

f:id:corocn:20181203183924p:plain

最終的に認証機能を付与するので、ALBのエンドポイントはHTTPS対応しておく必要があります。ドメインや証明書の準備が必要です。

今回は https://api.corocn.me/ というAPIを作ってみました。(いつもはお名前.comでドメインを取得してるので、Route53で取得してACMで証明書も取得してみました。)

f:id:corocn:20181203183445p:plain:w300

叩くとこんな感じで返ってきます。

Googleの OAuth2.0 クライアントを作成する

ALBにGoogle認証を追加します。事前にGCPでOAuth 2.0のクライアントを作成しておきます。

「OAuth同意画面」から アプリケーション名を入力するのと、承認済みドメインにALBに紐づけたドメイン名を追加しておきます。

f:id:corocn:20181203184546p:plain:w500

認証情報を作成からOAuthクライアントIDを選択します。

f:id:corocn:20181203184727p:plain:w500

リダイレクト先は次の値を設定します。

https://<YOUR_DOMAIN>/oauth2/idpresponse

ALBの認証リダイレクトはこのパスで固定です。

f:id:corocn:20181203185112p:plain:w500

クライアントIDとシークレットは後ほど設定するので控えておきます。

ALBにOIDC認証を追加する

ALBのルール設定で認証ルールを追加します。

CognitoやOIDC(OpenID Connect)が使えますが、Google認証を使うのでOIDCです。

f:id:corocn:20181203185421p:plain:w500

f:id:corocn:20181203185722p:plain:w500

ポイント

  • クライアントID・シークレットは控えておいた値を入力します
  • 一度設定したら、設定を更新するたびにシークレットの入力が必要になります。注意です。
  • スコープに「openid profile email」をすることで、名前やメールアドレスの情報が取得でき、Lambda側に渡ります。

各種エンドポイントは次のようになります。

設定情報は、OpenID Connect  |  Google Identity Platform  |  Google Developers に書いてありました。

Lambda側で認証情報を使う

Lambda側にはヘッダの x-amzn-oidc-data にJSON Web Token(JWT)形式で格納されます。JWTの詳しい仕様は、 JSON Web Tokens - jwt.io あたりを参照すると良いです。

require 'json'
require 'base64'

def lambda_handler(event:, context:)
    jwt = event['headers']['x-amzn-oidc-data']
    header, payload, signature = jwt.split('.')
    profile = JSON.parse(Base64.decode64(payload))
    {
        statusCode: 200,
        statusDescription: '200 OK',
        isBase64Encoded: false,
        headers: {
            'Content-Type': 'text/html; charset=utf-8'
        },
        body: "Hello, #{profile['name']}!! Your email is #{profile['email']}"
    }
end

JWTはBase64EncodeされたJSONがドット区切りでつながっているだけです。ペイロード部にprofile情報が含まれていますので、splitしてdecodeすれば必要な情報は取り出せます。

f:id:corocn:20181203191226p:plain:w400

認証情報をLambdaに引き渡すことができました。

特定ユーザーのブロック

現状ですとGoogle認証を通過した全てのユーザーがAPIにアクセス可能です。 例えばG Suiteの自組織内のみ認証を通したいという場合が考えられます。

この場合、Lambdaの最初でemailの値を見て弾くのが一番簡単な処理ですが、そもそもLambdaまで到達させたくありません。 本来であれば認証の段階でユーザーをブロックしたいと思うので、その場合は Auth0Amazon Cognito を活用して処理を組み込むことになりそうです。

最後に

証明書の設定は面倒ですが、API Gatewayよりもクセなく使えて簡単でした。 OIDCのIdPとしてAuth0と連携させようと思ったのですが、時間が無かったのでまたどこかで試してみようと思います。

「Auth0」で作る! 認証付きシングルページアプリケーション という本を書きました

タイトルの通り Auth0 と SPAの本を書きました。

https://amzn.to/2LN2Y6K

Auth0とは

Auth0 は 認証・ID管理を開発者に提供するクラウド認証プラットフォームです。 シンプルでアプリケーションに簡単に組み込めます。

WebTaskと呼ばれる、AWS Lambdaのようなサーバーレスなコード実行の仕組みを独自で持っていて、 JavaScriptなどでルールを記述することによって、名寄せなどの仕組みを簡単に実現できます。

Never Compromise on Identity. - Auth0

なぜこの本を書こうと思ったか

この本は、技術書典4で出版した同人誌の、商業版です。

blog.corocn.jp

プライベートでもアプリを書いたりするのですが、 認証の仕組みって意外と面倒だけど本来のビジネスロジックに関係ないんで、 ささっと実装して本当に実装したい部分に注力したいはず。でもセキュリティ怖いから適当できない。

例えばRailsにはDeviseやSorceryという認証系のライブラリがあるのですが、 もっとかっこよくスマートにログインさせたいという気持ちで、それを解決してくれる仕組みを探していました。

Firebase や AWS Cognito も試してみたのですが、一番シンプルで簡単でしっくりきたのがAuth0でした。 特に Cognito は難しい。Cognitoで何ヶ月も検討してダメだったけど、Auth0なら数日で実現できたという話も聞いてます。

認証関連の情報って少ない

認証の話ってセキュリティに直結するところなので、実装の話を企業はなかなか公開しません。 さらにSPAとなると、フロントエンドとバックエンドが明確に分離しているので、さっと試すのもなかなか大変です。

本書はAuth0 のタイトルが全面に出てしまっていますが、JWTを使った基本的な認証の仕組みを学ぶことが大きなテーマでもあります。 実際に手元で動かして、試してみてください。基本知識を身につけることで、 Auth0を使わない認証にも応用できるはずです。

むすび

そんなこんなで、勢いで同人誌を出したのですが、意外な反響があって、2018/08/31 に商業版として出版することができました。 この場を借りて皆様に感謝申し上げます。

大筋は一緒ですが、書き足りないなと思っているところを加筆していったら、ほぼ倍のページ数になりました。 ぜひお手にとっていただけると嬉しいです。

「Auth0」で作る!認証付きシングルページアプリケーション | 電子書籍とプリントオンデマンド(POD) | NextPublishing(ネクストパブリッシング)


以下、Twitterの声を引用させていただきました。

結婚した。そして30歳になる。

@corocn です。

結婚しました。

出会いは某大手マッチングアプリのOでした。 最近は割と一般的みたいです。周りにもたくさんいる。

相手はエンジニアでは無いけれど、自分の仕事観を良く理解してくれている人なので嬉しい限り。 ヒィヒィ言いながら技術書典4の執筆してた時期も、めっちゃ応援してくれました。

所属する会社の働きやすさがピカイチなので、一緒にいる時間が十分取れています。

f:id:corocn:20180813214408p:plain:w300

会社のesaのトップにはこう書いてあるんですよ。最高じゃないですか? 未来永劫今の会社で働いているか分からないけど、家族を大事にする働き方は変えないぞという固い決意をしています。

なお挙式はしませんでした。その分家具家電に全力投資して一緒にいる時間を増やしています。 食洗機、ドラム式洗濯機、ルンバあたり本当に便利。生活の質が爆上がりしてます。

そして、

明日には30歳になるんですよ。

グッバイ20代。まだ28歳ぐらいの感覚だったんですが、なんとまあはやいことで。

今まではフロントからインフラまで雑にやってたんですが、そろそろ技術的な強みがほしい。 院卒後キャリアチェンジしてるので、同世代に比べたらとてもとてもビハインドしている実感。

エンジニアリング的なところだと、ユーザーに価値を届け続けるために、 変化に強くて攻めの開発ができるインフラや開発基盤を構築していきたいんだ!という気持ちです。

組織づくり的なところだと、最近はエンジニア採用が楽しいので引き続きやっていきます。 自分の書くリクルーティングDMが各所で話題になっているようなので嬉しい限りです。

引き続きよろしくお願いいたします。

最後にいつものアレです→ http://amzn.asia/i5mOrlx

IntelliJ 組み込みterminalでfish-shellを使う

shellをfishに置き換えたのは良いが、IntelliJの組み込みTerminalで動かなかったので直した。

stackoverflow.com

IntelliJのapp内にもconfig.fishがあってそっちを読んでるのが問題っぽい。 stackoverflow見るとfunctionsの読み込み処理追加しろよ〜って記述があるんだけど、追記しても不安定なので

You could also just replace that whole fish directory in IntelliJ's plugins/terminal with a symlink to your normal fish config directory, usually .config/fish/.

これに沿ってsymlinkで置き換えたほうが良かった

osx + IntelliJ Ultimate の場合

cd /Applications/IntelliJ\ IDEA.app/Contents/plugins/terminal/
mv fish bak.fish
ln -s ~/.config/fish fish

以上