Grails2.0.2以降のbinding機構にハメられた件

ハマった。

Grails2.0.0で実装途中だったプロダクトを2.0.3に上げてみたらテストが通らなくなった。

半端なバージョンだけれども、例のgithubでもあったRailsの脆弱性と同じ問題に対処するために、Grails2.0.2からコントローラ上でhoge.properties = params や new Hoge(params)としたときにすべてのプロパティをがっつり反映しないように制御できるようになっています。
http://blog.springsource.org/2012/03/28/secure-data-binding-with-grails/

transientsなプロパティは明示的にbindable:trueしないと、そのプロパティはバインドされないようになってました。

In Grails 2.0.2 the data binding mechanism will by default exclude all properties which are static, transient or dynamically typed.

前述のブログにしっかり書いてた。staticとtransientと動的型はデフォルト除外(bindable=false)だそうな。

一度きちんと整理しないといけないなーとは思うけど、とりあえず試した結果をはっておく。

bindable:trueを設定した場合、これはグリーン

class Book {
    String name
    String author
    String transientField

    static transients = ['transientField']

    static constraints = {
        transientField bindable:true
    }
}
import grails.test.mixin.TestFor
import org.junit.Test

@TestFor(Book)
class BookTests {

    @Before
    void setUp() {
        mockForConstraintsTests(Book)
    }

    @Test
    void constraintsOfTransientField() {
        def book = new Book(name: "NAME", author: "AUTHOR", transientField: "TRANSIENT!")

        assert book.name == "NAME"
        assert book.author == "AUTHOR"
        assert book.transientField == "TRANSIENT!" // 設定される
    }
}

bindable:falseを設定した場合、これはグリーン

class Book {
    String name
    String author
    String transientField

    static transients = ['transientField']

    static constraints = {
        transientField bindable:false
    }
}
import grails.test.mixin.TestFor
import org.junit.Test

@TestFor(Book)
class BookTests {

    @Before
    void setUp() {
        mockForConstraintsTests(Book)
    }

    @Test
    void constraintsOfTransientField() {
        def book = new Book(name: "NAME", author: "AUTHOR", transientField: "TRANSIENT!")

        assert book.name == "NAME"
        assert book.author == "AUTHOR"
        assert book.transientField == null // 反映されてない
    }
}

constraintsで明示指定しない=transientなプロパティのデフォルトbindable:false、これはグリーン

class Book {
    String name
    String author
    String transientField

    static transients = ['transientField']
}
import grails.test.mixin.TestFor
import org.junit.Test

@TestFor(Book)
class BookTests {

    @Before
    void setUp() {
        mockForConstraintsTests(Book)
    }

    @Test
    void constraintsOfTransientField() {
        def book = new Book(name: "NAME", author: "AUTHOR", transientField: "TRANSIENT!")

        assert book.name == "NAME"
        assert book.author == "AUTHOR"
        assert book.transientField == null // 反映されてない
    }
}

constraintsで明示指定しない=通常のプロパティのデフォルトbindable:true、これはグリーン

class Book {
    String name
    String author
    String transientField
}
import grails.test.mixin.TestFor
import org.junit.Test

@TestFor(Book)
class BookTests {

    @Before
    void setUp() {
        mockForConstraintsTests(Book)
    }

    @Test
    void constraintsOfTransientField() {
        def book = new Book(name: "NAME", author: "AUTHOR", transientField: "TRANSIENT!")

        assert book.name == "NAME"
        assert book.author == "AUTHOR"
        assert book.transientField == "TRANSIENT!" // 反映された(まあname, authorとかわらんのだけど)
    }
}