Material UI + TypeScript で withStyles (JSS) を型付きで使う
Material-UI を使い始めて数日が経ち、ようやくJSSの思想が飲み込めてきました。 当初の違和感もだんだん薄れ、今では(今のところは)確かに楽だよねという感覚になってきております。
今回は型定義についてです。
import * as React from 'react' import { createStyles, Theme, WithStyles, withStyles } from '@material-ui/core/styles' interface Props extends WithStyles<typeof styles> { // my props... } function MyComponent({ classes }: Props) { return ( <div className={classes.root}> {/* my contents... */} </div> ) } const styles = createStyles({ root: { // my styles... }, }) export default withStyles(styles)(MyComponent)
と定義すると classes.xyz
のように styles
変数の定義に存在しない ClassKey
にアクセスしようとするとエディタが怒ってくれるようになります。
typeof styles
で styles
オブジェクトを型の世界に持ち込んでいるのがみそですね。
関数形式の styles
を利用する場合は以下のようにします。
const styles = ({ spacing }: Theme) => createStyles({ root: { // my styles... }, })
始めは createStyles((theme: Theme) => ({ ... }))
と定義しようと勘違いしておりました。
そして後から気づいたのですが、今回の内容は全部 https://material-ui.com/guides/typescript/ に書いてありましたね。
Material UI + TypeScript で Mixin を定義する
TypeScript + Materia UI でアプリを書いていて、テーマ関係のメソッドの中に createMixins
というものを見つけたので使い方を調べてみました。
デフォルトの mixin といえば gutter
くらいしかなくて、自分でも登録できたら色々使えそうだな...と思い、型定義を追いかけながらコードを試行錯誤したところ、多少不恰好ですが動くものができたのでメモしておきます。
プロジェクトコードは以下のリポジトリにあります。
プロジェクト作成
プロジェクトは create-react-app
の react-scripts-ts
で生成したものをベースにしています。この辺は特に詳細は説明しません。
create-react-app practice-mui-with-jsonschema-form --scripts-version=react-scripts-ts --use-npm
Theme の定義
Theme
を定義しているファイルの全体のコードは以下のようになります。
import { createMuiTheme } from '@material-ui/core/styles' import createMixins from '@material-ui/core/styles/createMixins' import { CSSProperties } from '@material-ui/core/styles/withStyles' // `Mixins` 定義を拡張する declare module '@material-ui/core/styles/createMixins' { interface Mixins { myBackgroundMixin: CSSProperties, // <- custom mixin! } } // `createMixins` で利用するインスタンスを取得する const { breakpoints, spacing } = createMuiTheme() const mixins = createMixins(breakpoints, spacing, { myBackgroundMixin: { backgroundColor: '#ff0000' } }) export default createMuiTheme({ mixins, palette: { divider: '#ff0000' }, })
以下、個々のポイントを説明していきます。
Mixin の定義を拡張する
createMixins
で参照されている interface Mixins
の定義を見ていると何やら意味深なコメントが書いてあります。
export interface Mixins { gutters: (styles?: CSSProperties) => CSSProperties; toolbar: CSSProperties; // ... use interface declaration merging to add custom mixins }
TypeScript の柔軟であり分かりづらい部分ですが、interface
などの定義は後追い拡張(マージ)が行えます。
ここでは以下のように myBackgroundMixin
を追加定義してみました。
declare module '@material-ui/core/styles/createMixins' { interface Mixins { // (=˘ ꒳ ˘=) 展開先を赤く染め上げる血みどろの Mixin... myBackgroundMixin: CSSProperties, } }
Mixin の定義を行う
これにより createMixins
の引数である MixinsOptions
にも拡張が反映され、createMixins
内で myBackgroundMixin
が定義できるようになります
const mixins = createMixins(breakpoints, spacing, { // (=˘ ꒳ ˘=) 血みどろの実装...容赦のないビビッドな赤 myBackgroundMixin: { backgroundColor: '#ff0000' } })
上の定義の拡張を行わないと Object literal may only specify known properties, and 'myBackgroundMixin' does not exist in type 'MixinsOptions'.
というエラーが出ます。
ちょっと曲者な createMixins の引数
createMixins
の引数には Breakpoint
と Spacing
のインスタンスが必要なのですがいちいち用意したくはないですよね。今回は小手先のアイディアとして一度 createMuiTheme()
を実行してデフォルトのインスタンスを取得しています。
const { breakpoints, spacing } = createMuiTheme()
もっといい方法がある気がしますね。
実際に利用してみる
上記の定義を含めた Theme
インスタンスを MuiThemeProvider
経由で提供してやれば、配下のコンポーネントで今回定義した myBackgroundMixin
を利用することができます。
import * as React from 'react' import Button from '@material-ui/core/Button' import { createStyles, Theme, withStyles, WithStyles } from '@material-ui/core/styles' interface Props extends WithStyles<typeof styles> { name: string } function MyButton({ classes, name }: Props) { return ( <Button className={classes.root}> {name} </Button> ) } const styles = ({ mixins, palette }: Theme) => createStyles({ root: { ...mixins.myBackgroundMixin, color: palette.common.white, } }) export default withStyles(styles)(MyButton)
無事、手元では赤いボタンが表示されました。
ここまで、細切れの説明になりましたので、冒頭で紹介したリポジトリで全体を見ていただくのが分かりやすいかもしれません。
VSCode の Atom One Dark テーマをもう少しシックにカスタムする
ひと昔前まで Atom を使っていたのですが builtin terminal を始めとした機能性には抗えず VSCode に移行したのは記憶に新しいところです。
Atom の良かった点は何と言ってもあの、コーディングに最低限必要な情報以外を切り捨てたインタフェースです。ボタンの種類が少ないのもありますが、色使いのノイズの少なさは初めて見た時に目がハートマークになるくらいに気に入ったところです。
まさに私がエディタに求めていたものでした。
VSCode に移行するにあたって最後の後ろ髪になったのがこのカラーテーマで、何しろ VSCode のデフォルトのスタイルではこのように...
青色のステータスバーがチカチカするわ、ボタンが多いわ、バッジが目立つわで Atom のあのデザイン大好き人間からすると直視に耐えない(言い方が悪い)ユーザインタフェースです。機能が多いのはいいのですが、別に常に見えている必要はなく、そもそも使わないコントロールが大半だったりで、もっとこう何というか Zen な感じが欲しいんです。
VSCode の機能性は捨てがたい、しかしこのノイジーなインタフェースは...という葛藤。
で、VSCode には Atom One Dark という Atom のデフォルトのダークテーマをベースにしたテーマパッケージが存在します。それを適用すると以下のようになります。
とてもシックになりましたね。十分と言えば十分なのですが、まだ Atom には存在しない左端のバー(Activity Bar)が存在するのが気になります。どうでもいいと言えばいいのですがやっぱり気になります。ボタンなど少ないに越したことはないのです。しかし消したら消したで不便なので目立たせない方向性で微調整をしていきたいと思います。ついでにバッジの色も目立たないようにしていきます。コーディング領域以外は基本出しゃばらせたくはありませんね。
試行錯誤 & カラーピッキング & コピペの成果で以下のスタイルに行き着きました。
設定はこんな感じで行いました。差分だけ貼っておきます。
"explorer.openEditors.visible": 0, "workbench.iconTheme": "vs-minimal", "workbench.colorCustomizations": { "activityBar.background": "#20252C", "activityBar.foreground": "#626C83", "activityBarBadge.background": "#567", "badge.background": "#20252C", "statusBar.background": "#20252C", "statusBar.noFolderBackground": "#222225", "statusBar.debuggingBackground": "#511f1f", "gitDecoration.ignoredResourceForeground": "#5B6270", "list.inactiveFocusForeground": "#444", "sideBar.background": "#20252C", "sideBarSectionHeader.background": "#20252C", "foreground": "#999", "terminal.foreground": "#999", "terminal.ansiRed": "#E26B73", "terminal.ansiGreen": "#96C475", "terminal.ansiBlue": "#5DADF1", "terminal.ansiCyan": "#51B6C3", "terminal.ansiMagenta": "#C774DF", "terminal.ansiYellow": "#E5C076", }, "workbench.colorTheme": "Atom One Dark",
設定項目は VS Code Theme Color Reference を見ながら行いました。 色以外の設定項目は以下の通りです。
"explorer.openEditors.visible": 0
はファイルツリーと同じペインに表示される「Open Editors」を消しています- ペイン中のウィジェットが単一になるとメニューバーが上端にマージされるようなのでかなり見た目のノイズが減ります
"workbench.iconTheme": "vs-minimal"
はデフォルトのアイコンがカラフルすぎるのでシックなものを採用しました
Atom だとウィンドウの上の白いバーが目立っていましたが、VSCode の場合はその領域もデザインに統合されているので、結果的に Atom 以上にシックなデザインにカスタマイズできたと思います。
ここまでやったらもう Atom に未練は無くなりました。ありがとう、Atom はとても素晴らしいエディタの形を私に見せてくれました。Atom のもたらしてくれたものを思い残すことなく VSCode に引き継ぎ、これからも思う存分 VSCode の機能性を満喫したいと思います。
最後にもう一度 Atom を見ておきます。エディタの表示面だけで言えばひとつの完成形です。
そして今回の VSCode を。
まだちょっと肩のボタンが多いですね。こういうのでも消せたら嬉しい人間はまちがいなくこの世に存在するのです。また時間があったらリファレンスを漁ってみます。
設定ファイルは myhome/settings.json at master · asa-taka/myhome · GitHub で管理していますので、最新版が気になる方は見ていただければと思います。
Wireshark でTLSの通信を読む
TLSの勉強中です。TLSの通信を眺めるにはやっぱりHTTPSだろうということで簡単なHTTPSサーバを立ててトラフィックを眺めてみたいと思います。『プロフェッショナルSSL/TLS』にも書かれていました。「一番良い方法は実際のパケットを見ることです」と。
下準備
Caddy を利用します。HTTPSとHTTP用の設定ファイルを用意します。
$ tree . ├── Caddyfile.http ├── Caddyfile.https ├── cert.pem ├── key.pem └── public └── index.html $ cat Caddyfile.http :8080 root public $ cat Caddyfile.https :8443 tls cert.pem key.pem root public
自己署名証明書は以下のコマンドで生成しました。
$ openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -nodes
HTTPS通信を覗いてみる
Wireshark 上であらかじめ lo0
をキャプチャする設定で待ち構えておきます。
フィルタは tcp.port == 8443
に設定しておきます。
$ caddy -conf Caddyfile.https
でサーバを立て
$ curl -v --insecure https://127.0.0.1:8443
で叩きます。
総パケット数は 39 でした。
HTTP通信を覗いてみる
$ caddy -conf Caddyfile.http
でサーバを立て
$ curl -v http://127.0.0.1:8080
で叩きます。
総パケット数は 14 でした。
サンプルプロジェクト
以上のような設定をまとめて GitHub に上げておきました。ご参考になれば幸いです。
『PKIハンドブック』覚え書き
2000年初版の『PKIハンドブック』が中古でお安かったので覚え書きを残していきます。
2015年出版の『プロフェッショナルSSL/TLS』と並行して読んでいるので気になる部分があれば抜き出してみようと思ったのですが...初心者的な視点から見ると特に目立った差異はありませんでした。 今後気をつけて読んでいきたいです。
「SSL Ver3.0 からバージョンアップしたTLSを基に解説する」と本文にありますが、 普段から数年単位で要素技術や仕様がガラリと変わり得るフロントエンドの技術調査をすることが多い身からすると笑ってしまうくらい変わっていませんね。 それだけ学習量対効果に秀でた技術領域なのかな、という感触を受けています。 一度学んでおけば数十年単位で土台となる技術が身につくという。
この辺はHTTPも似たようなものですね。 そしてPKIと言えばSSLで、SSLと言えばHTTPSです。 フロントエンド側の人間でも Docker やデプロイ系の領域に手を伸ばし始めるとこの辺りの知識の有無が利いてきますね。 もしくはマッシュアップ方面の方がHTTPSには馴染みが深かったりするのでしょうか。
とにかく、日常で触れる機会も実は気にしてみると結構多かったりする領域なので、このあたりの仕組みや語彙はフロントエンドのトラブルシュートにも結構な係数で利いてくると思います。 という期待を込めて『PKIハンドブック』を読んでいきたいと思います。
本書を読むにあたり
18年前の本書を読むことについて
2018年現在、2000年初版の本書を読むことに対し、個人的に意義であると感じていることです。
- 『プロフェッショナルSSL/TSL』とは別視点の本を読むことで概要把握の正確性の一助とする
- (フロントエンド技術と比較して)息の長い技術がこの期間でどの程度変化したかに素朴に興味がある
- 素朴に歴史、隔世の感を感じたい
勉強半分、趣味半分といったところです。
どんな技術にも起こり、流行り、廃りの流れがあり、そしてその流れを追いきれなかった現実のシステムは恐らく大量に残されていて、この先自分もどこかでそれに出くわすだろうと。 スナップショットでない、時間幅を持った知識や経験って、もしかしてそういうところで活きてくるんじゃないかなと。 「昔の本を読む」という単なる追体験、真似事ですが、それでも年表を追う以上の何かが得られたらいいなと思っております。
現在の興味領域に照らし合わせ、PKIの仕組みから運用のかじりについて触れられている第8章までを読んでいくつもりです。
SSL/TLS簡易年表
年 | SSL | TLS | 備考 |
---|---|---|---|
1994 | 2.0 | - | Netscape |
1995 | 3.0 | - | Netscape |
1995 | (3.1) | 1.0 | |
2006 | (3.2) | 1.1 | |
2008 | (3.3) | 1.2 | |
2018 | (3.4) | 1.3 |
1. PKI の基礎知識
- 脅威の種類
- 盗聴、なりすまし、改ざん、事後否認
- 事後否認は初耳でした、情報の発信者側から内容が改ざんされていると主張することですね
- 共通鍵暗号方式
- 公開鍵暗号方式(非対称鍵暗号方式)
- RSA(1978)
- その他の暗号方式・署名方式
- 一方向性ハッシュアルゴリズム
- メッセージ認証(完全性保証)
- 以下のMICとHMACは秘密情報と一方向ハッシュを利用したもの*3
- MIC(Message Integrity Checksum)
- HMAC(Keyed-Hashing for Message Authentication)
- デジタル署名(完全性保証)
- 公開鍵暗号方式と一方向性ハッシュを組み合わせた完全性保証の方式
- 相手認証
- 鍵配送
2. 公開鍵基盤
- PKIの要素と役割
3. 公開鍵証明書と失効リスト(CRL)
読み進め次第追記するつもりです... ˘ω˘
*1:つまり共通鍵暗号と公開鍵暗号には「計算量」と「鍵の管理の手間」の間にトレードオフがあると考えられるのでしょうか
*2:「離散対数問題」が利用されている手法が多いので掘り進めてみたいですね。他に ElGamal の方式もその応用例として挙げられていました。
*3:完全性の検証はどう行うのか、秘密情報を共有していること前提か。つまり「メッセージ認証は共通鍵的なものでデジタル署名は公開鍵暗号方式を利用したもの」という認識でいいのでしょうか。
*4:つまり秘密鍵の漏洩はこの前提を覆し、その「本人」に対する相手認証が全て機能しなくなるということになりそう。
*5:この信頼できる第三者の存在を前提とした「信頼モデル」と呼べるものは初見ではどこか情報工学っぽくない感じもしますが、実際の社会の「信頼」という概念も結局はこんなところなのでしょうね。現実世界の反映と考えると次第に慣れていきます。
Protocol Buffer と gRPC を Go で使うときのリポジトリを整理する
(=˘ ꒳ ˘=) google と golang がぱっと見ややこしい...
Protocol Buffer と gRPC を Go で利用しようとすると色んなリポジトリからツールを落としてくる必要がありますがどれも微妙に字面が似ているので混乱します。それらを整理するために org/repo の形式で一覧できるようにまとめていきたいと思います。
まず Protocol Buffer のコアなツールが含まれるリポジトリが
- google/protobuf
- C++ 製の Protocol Buffer のコア
- 含まれるツール: protoc
- 日付型などの well-known 型の
.proto
定義も含まれる
ですね。Go の場合はこれに加えて Protocol Buffer と gRPC の Go 実装のためのパッケージが必要になります。
.proto
定義からコードを生成したり、そのコードから import
されるパッケージが以下のリポジトリに含まれます。
- golang/protobuf
- 含まれるツール: protoc-gen-go とその grpc プラグイン
- 生成された
.pb.go
のコードからimport
される Protocol Buffer の Go 実装 - 日付型などの well-known 型の Go 実装も含まれる
- その日付型と time パッケージの日付型を変換するためのユーティリティなども含まれる
- grpc/grpc-go
C++やPHPなど Go 以外の言語だと grpc のメインのリポジトリでその辺が間に合ってしまいそうです。
上に書いた通り grpc_cli は便利なので Go でもこのリポジトリの一部機能は利用する、という感じです。
...ややこしいですね。
まだ書き出しただけで、プラグインやら well-known 型の定義や実装がどこにあるかやらが整理できているとは言い難いですが、使っているうちに慣れるのでしょうか...
gRPC で日付型を利用する
(=˘ ꒳ ˘=) gRPC の import 周りを整理したい...
という記事で go-proto-validators と grpc_cli をうまく組み合わせられないことに対して試行錯誤してました。
その問題の切り分けがてら、今回はもう少し基本的な日付型の利用を通して gRPC の import 周りを整理していきたいと思います。
- プロジェクト: https://github.com/asa-taka/hello-validated-grpc
- 日付型を組み込んだコミット: https://github.com/asa-taka/hello-validated-grpc/commit/4d3d2251f5da298f6d64534b0aa7fdc29da63914
hello.proto をベースに日付型をレスポンスのタイムスタンプとして追加しています。
syntax = "proto3"; package hello; import "google/protobuf/timestamp.proto"; service GreetingService { rpc Hello(GreetingRequest) returns (GreetingResponse); } message GreetingRequest { string name = 1; } message GreetingResponse { string message = 1; google.protobuf.Timestamp date = 2; }
注意点としては Timestamp
ではなくて google.protobuf.Timestamp
と指定するところくらいです。
サーバ側の実装は今回も Go で、日付型の変換に https://godoc.org/github.com/golang/protobuf/ptypes#TimestampProto を利用しています。
Go の time
パッケージの日付型はそのままだと gRPC 用に吐き出されたコードには利用できません。
詳しい実装は冒頭のコミットのリンクをご参照ください。
で、リフレクションサービスは組み込み済みで肝心の grpc_cli の動作確認ですが...
$ grpc ls -l localhost:10000 filename: grpc_reflection_v1alpha/reflection.proto package: grpc.reflection.v1alpha; service ServerReflection { rpc ServerReflectionInfo(stream grpc.reflection.v1alpha.ServerReflectionRequest) returns (stream grpc.reflection.v1alpha.ServerReflectionResponse) {} } filename: api/hello.proto package: hello; service GreetingService { rpc Hello(hello.GreetingRequest) returns (hello.GreetingResponse) {} } $ grpc call localhost:10000 Hello "name: 'asa-taka'" connecting to localhost:10000 message: "Hello, asa-taka." date { seconds: 1527964860 nanos: 432266000 } Rpc succeeded with OK status
なんか普通に動いてしまって拍子抜けです。
import パス周り、意外と単純なのか根が深いのか... gRPC と Protocol Buffer 難しい...