Lambdaカクテル

京都在住Webエンジニアの日記です

Invite link for Scalaわいわいランド

Redacted: Scalaのcase classの特定のフィールドを隠すコンパイラプラグイン

Redditを見ていたところ面白いコンパイラプラグインを発見したので紹介する。

Redacted

Redactedは、case classの特定のフィールドをtoString()から除外し、***で塗り潰して見えなくできるコンパイラプラグインだ。

polentino.github.io

github.com

RedactedはScala 2.13系と3系の両方に対応しており、JVMでの動作が可能だ(Scala.jsとScala Nativeには対応していないようだ)。

百聞は一見に如かず、つまり以下のようなコードを書けるようになる:

import io.github.polentino.redacted.*

case class User(id: Int, name: String, @redacted password: String)

@main def hello(): Unit =
  val u = User(42, "windymelt", "foobar2000")
  println(u)

このコードを実行すると、以下の出力になる:

User(42,windymelt,***)

この作用により、うっかり秘匿しなければならないデータを持つcase classを表示してログに残ってしまう、ということを防げる。

インストール

Redactedは2つの形式で提供されている。すなわち、sbtプラグインと、手動でコンパイラプラグインを導入する形だ。どちらを選択しても実現できることは同じだ。

簡単なのはsbtプラグインなので、特に理由がなければこちらを選ぶとよいだろう。

sbtプラグイン

project/plugin.scalaに以下の通り追記する(バージョンは執筆時点での最新):

addSbtPlugin("io.github.polentino" % "sbt-redacted" % "1.1.0")

次に、build.sbtに以下の設定を行い、プロジェクトでプラグインを有効にする:

lazy val root = (project in file("."))
  .enablePlugins(RedactedPlugin)
  .setting(
    redactedVersion := "0.9.0",
    // ...
  )

これだけでよい。

手動でやる

手動でやる場合はbuild.sbtで以下のようにする:

libraryDependencies ++= Seq(
  "io.github.polentino" %% "redacted" % "0.9.0" cross CrossVersion.full,
  compilerPlugin("io.github.polentino" %% "redacted-plugin" % "0.9.0" cross CrossVersion.full)
)

使い方

使い方はとてもシンプルで、case classのフィールドに@redactedアノテーションを配置するだけだ。というかこれ以外の機能は一切ない。

  • case classの
  • 任意のフィールドを
  • 隠匿する

これだけ。

import io.github.polentino.redacted.* // アノテーションをインポートする

case class Payment(id: Int, user: Int, @redacted creditCardNumber: String)
println(Payment(42, 100, "1234-5678-9012-3456")) // => Payment(42, 100, ***)

@redactedがあるフィールドを持つcase classは、自動的にtoString()が上書きされ、画面に表示した際にそのフィールドが***で塗り潰されるようになる。

ちなみに、直接フィールドにアクセスした場合は何の変更も加えられない:

val p = Payment(42, 100, "1234-5678-9012-3456")
println(p.creditCardNumber) // => 1234-5678-9012-3456

RedactedはあくまでもtoString()でうっかり漏れてしまうことを防ぐためのプラグインであり、それ以外の仕事はしないという姿勢に徹している。わざわざ隠しているフィールドにアクセスしているということは余計な心配は不要だろう、というわけだ。

注意

Redactedはコンパイラプラグインだ。ということは、Scalaのバージョンが上がり、なおかつコンパイラのAPIに破壊的な変更が起こった場合、このプラグインは追従しなければならず、その間はScalaをアップデートできないリスクがある。この点だけ注意が必要だ。

とはいっても、RedactedはScala 3.3系のLTSに対応しているので、アプリケーションをLTSで実行しているなら当面の間は問題ないだろう。ちなみに動作はScala 3.7.0で確認したため、今のところ最新版のScalaでも問題なく動作している。

サンプル

github.com

確認に使ったサンプルコードはこれ。

★記事をRTしてもらえると喜びます
Webアプリケーション開発関連の記事を投稿しています.読者になってみませんか?