メモ2ブログ

メモtoウェブログ。旧ブログはこちら。 http://sakebook.blogspot.jp/

Flutterで秘匿情報を扱う

最近Flutterを触ってます。

Gitなどに載せたくない情報の扱い方についてのメモ。2つの方法を取り上げます。

.env + flutter_dotenv

flutter_dotenvを使います。pubspec.ymlに以下を追加して

  • pubspec.yml
dependencies:
  ..
  flutter_dotenv: ^2.0.1
..
flutter:
  ..
  assets:
  - .env
$ flutter pub get

を実行します。

上の例ではプロジェクトルートに .envというファイルを置く想定です。

  • .env
SAMPLE_VALUE=this is dot env value.

main関数のはじめに初期化します。

void main() async {
  await DotEnv().load('.env');
  runApp(DotenvApp());
}

次のように呼び出します。

class DotenvApp extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text("Dotenv App"),
        ),
        body: Center(
          child: Column(
            children: <Widget>[
              Text(
                'dotenv values: ${DotEnv().env["SAMPLE_VALUE"]}',
              ),
            ],
          ),
        ),
      ),
    );
  }
}

Map<String, String>型なので取り出して適宜キャストして利用します。

一度初期化したらどこからでも呼べます

flutterパッケージに依存しているのでFlutter for Webでは利用できません。

JSON + json_serializable

json_serializableを使います。pubspec.ymlに以下を追加して

  • pubspec.yml
dependencies:
  ..
  json_annotation: ^2.4.0
..
dev_dependencies:
  ..
  build_runner: ^1.0.0
  json_serializable: ^3.0.0
..
flutter:
  ..
  assets:
  - secret.json
$ flutter pub get

を実行します。

上の例ではプロジェクトルートに secret.jsonというファイルを置く想定です。

{
  "value": "secret value",
  "num":  20190606
}

JSONは末尾カンマを許してはくれないので注意しましょう

対応するモデルを作成します。

part 'secret.g.dart';

@JsonSerializable()
class Secret {
  final String value;
  final int num;

  const Secret(this.value, this.num);

  factory Secret.fromJson(Map<String, dynamic> json) => _$SecretFromJson(json);
}

このままだと自動生成されたコードがないので、エラーになります。コードを生成します。

$ flutter pub run build_runner build

これでエラーは消えます。

JSONファイルを読み込んでモデルを返すクラスを用意します。

  • secret_loader.dart
class SecretLoader {
  final String secretPath;
  SecretLoader({this.secretPath});

  Future<Secret> load() {
    return rootBundle.loadStructuredData<Secret>(this.secretPath,
        (jsonStr) async {
      final secret = Secret.fromJson(json.decode(jsonStr));
      return secret;
    });
  }
}

準備はできました。次のように呼び出します。

class SecretApp extends StatelessWidget {
  final SecretLoader loader = SecretLoader(secretPath: "secret.json");

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text("Secret App"),
        ),
        body: FutureBuilder<Secret>(
          future: loader.load(),
          builder: (context, snapshot) {
            if (!snapshot.hasData) {
              return Center(
                child: CircularProgressIndicator(),
              );
            }
            final secret = snapshot.data;
            return Center(
              child: Column(
                children: <Widget>[
                  Text(
                    'secret value: ${secret.value}',
                  ),
                  Text(
                    'secret num: ${secret.num}',
                  ),
                ],
              ),
            );
          },
        ),
      ),
    );
  }
}

SecretLoader#loadの返り値がFuture型なのでFutureBuilderを使ってます。

内部で保持する仕組みはないので、その他の変数と同じように呼び出したスコープ内でしか扱えません

flutter_dotenvのときのようにmainで呼び出して、コンストラクタで必要なWidgetに値を渡しても良いと思います。

flutterパッケージに依存していないのでFlutter for Webでも利用できます。その際はJSONファイルをweb/assets/に配置します。

まとめ

どちらも一長一短あります。秘匿情報の利用が初期化時のみで済むのならJSON + json_serializableの方が、若干の準備がありますが良いかなと思いました。構造を持てるのは大きな魅力です。さっと試す程度なら.env + flutter_dotenvのほうが手軽だと思います。

どちらの方法にしても、間違えて秘匿情報を書いたファイルをコミットしないように注意しましょう。

参考

flutter_dotenv / Flutter Package

Storing your secret keys in Flutter – Sócrates Díaz Severino – / Medium

JSON and serialization / Flutter

DockerHubでAutomated Buildsを使った時にDocker Tagがうまく設定できない

OpenSSLでファイルの暗号化/復号化をしたくてAlpineベースのDockerイメージを作成しました。

github.com

ググったら同じようなものがあったのですが、OpenSSLのバージョンやCA証明書が古かったりで使いにくかったので作成しました。

どのバージョンのOpenSSLが入っているか・または指定できるようにtagをつけて管理したいと思い、Automated Buildsでtagをpushした時に自動でつけられるようにしたかったのですが、ちょっとハマったのでメモ。

何をしたか

デフォルトでmasterブランチを対象に latest とtagを振ってくれるRULESがあるのですが、今回はtag名にしたかったので不要と思い削除しました。

f:id:sakebook:20190410012248p:plain
削除したRULES

その上でGitのtagを見てそれをDocker Tagになるように設定したのですが、 Docker Tag の部分がうまく指定できなくなりました。具体的には、何を入力しても latest になります。

f:id:sakebook:20190410012316p:plain
Docker Tagの{sourceref}がlatestに置き換わる

設定できそうに見えるのですが、保存すると Docker Taglatest に置きかわります。

latest tagを振るRULESが最低1つは必須なんだと思い、はじめにあったRULESを追加してもダメでした。

f:id:sakebook:20190410012347p:plain
latestあるけどダメだった

どうやら 一番上が優先される ようで、削除して latest が一番上に来るようにRULESを指定することで思ったように指定できるようになりました。

f:id:sakebook:20190410012413p:plain
設定できた状態

思えば latest のtagが振られていないものってないなと思い、それから逸脱するような指定はできないようになっているんだなと納得しました。

まとめ

  • RULESは上にあるものが優先される
  • latest tagの指定は必要
    • 一度tagをつけてAutomated Buildsに成功した後はlatest tagの指定を削除しても設定できるようになりました。一定の環境下でないと起きないのかもしれません。

参考

Set up Automated builds / Docker Documentation

2018年を振り返って

すでに2019年が10%以上過ぎてますが、2018年の振り返りをまとめてなかったのでまとめておきます。

はじめに目標としてたことに対して振り返ります。

目標としてたこと

  • 自炊の回数を増やす
    • 12月から自炊を再開しました。相変わらずパスタ一辺倒です。振り返ってみると、引っ越ししてから2年以上自炊をしてませんでした。すごい。
  • 体を鍛える
    • 結局何もしなかったです。しかし続きがあります。
  • Android以外のこともする
    • iOSアプリを作り始めたのはいいですがモチベーションと進捗の折り合いがつかず、結局頓挫しました。しかしそのときにReactorKitというFluxベースのフレームワークを使い、Fluxの世界に興味をもつことが出来ました。
  • Google Assistant周りの何かをする
    • Nature Remoとiftttの既成品の連携だけで、特に開発はしなかったです。
  • Fitbit ionicのWatchFace作る
    • 正しくはClockFaceなのですが、こちらは作ることが出来ました。追い込まれるとやっぱりやらざるを得なくなります。

結果だけ見ると着手は半分以上できてるという結果にはなりますが、個人的にはそんなにやったった感は感じてないです。むしろ出来てないなという感じです。新規アプリ開発も公開までしたものはありませんでした。

やったこと

インサイダー・ゲームの拡張を作ろうとした

インサイダー・ゲームというボードゲームがあるのですが、出現するワードがカードに書かれている限りなので、そのワードを拡張して楽しめるようにできるアプリを作ろうとしました。

  • ワードの分類
  • ワードの保存
  • ワードを追加する機能
  • 分類したワードを表示する機能

とかが必要になるので、始めにワードの分類をしようと思い、ベクトル化をするところまでやってモチベーションの灯が消えてしまいました。

DockerHubにもあげてあるので動かしてみることは出来ます。

github.com

技術書典に参加した

技術書典5に出店側として参加しました。そのときにClockFaceの作成と同人誌作成をしました。

詳細は別記事にまとめてあります。

sakebook.hatenablog.com

ClockWaceを作った

技術書典で本を出すにあたり、作ってみました。当初はApple Watchという名前を入れていたのですが、ストアでレビューで落とされてしましました。一粒で二度美味しい体験ができました。

競争相手があんまりいないからか、ユーザから問い合わせがちらほらくるので、2019年はガチなやつを一つ作りたいなと思ってます。

github.com

jib触った

前述のベクトル化するコードのdocker化や、会社でのツールなどに活用しました。

tech.jxpress.net

Kotlin/Nativeちょっと触った

AlfredのWorkflowに使いました。多分やってる人はまだ他にいないです。

tech.jxpress.net

趣味とかその他

ボドゲにハマった

ハマりました。どれくらいかと言うと、自分でも買うしゲムマにも行くしボドゲを作るワークショップにも参加するくらいです。

2018年にこれだけ買いました。

ちなみに今年もすでに買い始めてます。

コーヒーにハマった

家で豆を挽いて飲むようになりました。スタバみたいなカフェミストを家でも飲みたいと思い、クリーマーを購入しました。

あとはマキネッタを買って、より濃いコーヒーでカフェミストを作ったりしてます。夏には水出しアイスコーヒーも作りました。

ハンドドリップ用に計りを買いましたが、安定したドリップにも貢献してくれるしそれ以外にも便利なので計りは一家に一台おすすめです。

2019年

すでにいくつか始めていることがあります。

ジム通い始めた

周りにやるって言っちゃったので勢いで始めました。今の所苦なく続いてます。会社帰りに通えるのは自分の中でマストだなと思いました。形から入るので、アンダーアーマーのコンプレッションウェアも購入してます。

競プロ始めた

基礎が弱いのはわかっていたので、学ぼうと思い始めました、筋トレと同じく、目が出たと思うタイミングが来るのかもしれません。

目標

OKRの本を読んで、会社としても導入しています。個人の目標も時期を区切って、OKRという形でやってみようかなと思ってます(すでに1ヶ月経ってるけど)。