2009年10月29日木曜日

Grails+Acegi プログラム上でログイン・ログアウトさせる

Grailsのバージョンは1.2-M3
Acegi Security は 0.5.2

忘れないうちにメモ

import org.springframework.security.providers.UsernamePasswordAuthenticationToken as AuthToken
import org.springframework.security.context.SecurityContextHolder as SCH

class NantokaService {
def daoAuthenticationProvider

// ログイン処理
void systemLogin(String username, String password) {
def auth = new AuthToken(username, password)
def authtoken = daoAuthenticationProvider.authenticate(auth)
SCH.context.authentication = authtoken
}
// ログアウト処理
void systemLogout() {
SCH.context.authentication = null
}
}

こんな感じ

2009年10月28日水曜日

7 〜モールモースの騎兵隊〜

をいまさらプレイしてます。

いまさらすぎるタイトルですが、ヴィーナス&ブレイブス買いに行ったら500円で売っていたので。
事前にプレイしとくとちょっぴり嬉しい、とどこかで聞いたような気が…

戦闘システムにランダム要素ほとんどないんで、考えがいあって楽しいです。
一問一問出題されるクイズみたいな戦闘だし、飽きないで遊べてます。
これでランダムエンカウント、とかだったら途中で投げそう。

しかし、この騎士団の連中、プライドだけ高い無能集団みたいな描かれ方してますけど、
構成メンバー全員、職種「騎士」なんだよなぁ。
それ最強集団じゃないスか?
適当にローテーションしてるだけで大抵殲滅できそう。

2009年10月27日火曜日

GrailsのUrlMappingsから直接viewに飛ばすと、localeの読み込みがおかしくなる

Grailsのバージョンは1.2-M3

ここで四時間くらい詰まった…

開発中アプリのトップページ「localhost/sampleapp/」に、"messages_ja.properties"から読み込んだメッセージを表示させていたんです。
で、URLの末尾に「?lang=de」とかつけるとそのメッセージがドイツ語(messages_de.properties)に変わるはずじゃないですか。

でも、変わらなかったんですよね。ブラウザの設定から日本語を消しても、クッキーを消しても、ずっと日本語表示のまま。

こういうときはGoogleいったあと、JIRAでしょうか。
http://jira.codehaus.org/browse/GRAILS-3871
に原因が書いてました。

Grailsのデフォルトだと、UrlMappingsに
"/"(view:"/index")

って書いてて、トップーページをviewに直接遷移させてるんですけど、
この場合、そのviewでlocaleの変更ができなくなるみたい。

いちど
"/"(controller:"foo")
でコントローラーを呼び出して、その中でindex.gspをrenderするように修正することで直りました。


だいぶ有名な事象みたいだけど、これ、直るのかな…
JIRAみると、必殺技「仕様です」みたいにも読めるけど。

GrailsのTagLibテストケースの記述

Grailsのバージョンは1.2-M3

最近のフレームワークは、開発者がテストにハマるようにいろいろ趣向こらしていて助かりますよね。
RSpec on RailsとZenTestはもうすごいよかったなぁ…
Groovyでも似たようなのないですかね、RSpec on Grails みたいなヤツ。あとZenTestみたいなヤツ。

さて、Grailsも最近のフレームワークなので、テストは結構楽しくできます。
ですが、Grailsの1.2(1.1も?)だと、ドメインモデルだのコントローラーだのは、テストケースの中でnewしてもうまくいかないらしいです。(ダイナミックメソッドが注入されずエラーになるみたい 参考:Grails1.1.xのUnitテスト)

TagLibのテストでも、同じようにnewして実行すると、メソッドやプロパティが見つからないと言われて落ちることがあります。
TagLibのユニットテストを記述するTagLibUnitTestCaseには、tagLibプロパティがあって、対象となるTagLibがセット済みなのでそれを使えばいいみたいです。

Grails をマスターするのカスタムタグを例にすると、

×
class DateTagLibTests extends GroovyTestCase {
def dateTagLib

void setUp(){
dateTagLib = new DateTagLib()
}

void testThisYear() {
String expected = Calendar.getInstance().get(Calendar.YEAR)
assertEquals("the years don't match", expected, dateTagLib.thisYear())
}
}

class DateTagLibTests extends GroovyTestCase {
void testThisYear() {
String expected = Calendar.getInstance().get(Calendar.YEAR)
assertEquals("the years don't match",expected, tagLib.thisYear())
}
}

上だと、
groovy.lang.MissingPropertyException:No such property: out for class
とか言われて落ちました。

あ、でも各テストケースの中(setUpじゃなくて)でTagLibクラスをnewすると普通にテスト通りましたね。
よくわからんです。

WebFlowってRESTfulじゃないよね…

すくなくとも、Grails(てかSpring?)の実装だと。
まったく同じ画面なのに、リロードするとどんどんURLが変化していく…
あれ、複数のURLが同じリソースを指すのはいいんだっけ。でもWebFlowのURLって特に記述的な意味とかないし。
POSTのリクエストボディに制御パラメータ入れられないかな。

Grailsが最近取り入れてるRESTfulなURLマッピングと組み合わせようとすると、訳分からんことに。
なにかうまい方法ないでしょうか。よくわからない…
とりあえず、WebFlowについてよく理解できるまでは使わないようにします。

Grailsでのメール認証つきユーザー登録

Grails バージョンは1.2-M3

ユーザー登録画面

「仮登録メールを送信しました、本登録にはこのリンクにアクセスして云々」

本登録が完了しました

という、よくあるやつです。


次のふたつのプラグインで実現
  • 定番らしいユーザー認証プラグイン「Spring(Acegi) Security 0.5.2」(公式)
  • メールアドレス確認用プラグイン「Email Confirmation 1.0.3」(公式)
まあ、「Email Confirmation」のチュートリアルをやってみたら、なんとなく感じがつかめそうですが、実装はこんな感じで。

1.「Email Confirmation」にメールアドレス、入力されたユーザー情報(ログインIDとか)を渡す
[PersonController#save]
emailConfirmationService.sendConfirmation("sendto@sample.com", "メール本文", [from:"from@sample.com", view:"/path/to/mail-body-gsp"], "${loginid}\t${encordedPassword}")
emailConfirmationServiceはプラグインが提供しているServiceです。
こうすると "sendto@sample.com"にメールアドレス確認用のリンクがかかれたメールが送られます。最後に"${loginid}\t${encordedPassword}"でユーザー情報を登録してます。

2.「Email Confirmation」のアドレス確認完了イベントでユーザー登録
さて、メールに送信されたリンクを押すと、emailConfirmationServiceのonConfirmationイベントが発生します。
このイベントにはリスナとしてクロージャを登録するのですが、このクロージャの中でさっき登録した"${loginid}\t${encordedPassword}"がとれるので、分解してユーザーを構築してDBに格納して終了です。

Grailsのユーザー認証、認可用プラグインには今回使用したSpringSecurityの他にも、JSecurity(もう非推奨、今後はApache Shiro(何?)プラグインを使えといわれた)、Authentication Pluginなどいろいろあるんですが、どれ使っても同じ用に実装すればできるのかな? (ほとんど触ってないので分からないですが。)
というか、この辺のプラグインだとEmail Confirmation使わずにできたりしないかな…