当ブログに掲載しているサンプルは、すべて利用者の自己責任という形でお願いします。
ただし、明らかな不具合がある場合、ご連絡いただければ、訂正記事を出します。
また、こちらのサンプルは、別のサイト等への公開、転載は一切禁止しています。
どうしてもと言う場合は、筆者にあらかじめご連絡ください。
記事そのもののリンクについてはご自由に行っていただいてよいです。

テクてく Lotus 技術者 Slack に参加しよう!

2018年1月28日日曜日

フォームのアクセス権をプログラムで制御する

皆さん、こんにちは。
いつも冬になると寒いなぁと感じていますが、今年は特に寒さが厳しく感じますよね。
いつも2月が寒さのピークだと思っていますが、1月でこの寒さだと2月になったら・・・
考えるのも嫌になります。

さて、今日は前回(というか前日)の予告通り、
「フォームで文書を作成できるユーザー」の情報をLotusScriptで取得できないものかどうかを確認してみます。
Notes DBは前回作成したものを利用します。

1.なぜ確認するのか?

まずは、なぜ確認する必要があるのかを考えてみます。
少なくともNotesクライアントで利用している場合、「フォームで文書を作成できるユーザー」の設定が行われていれば、自動で制御が行われて、文書が異常に作成されることはなさそうです。
ただし、バックエンドで文書を作成後、その文書を編集するという荒業があるので、確認はできた方が良さそうです。
また、最近はNotesクライアントでの利用ではなく、Webブラウザからの利用を推進する動きもありますので、Webブラウザでの動作についても確認する必要があるでしょう。


2.Web画面で実行するとどうなる?

ということで、Webブラウザで実行するとどうなるかを確認してみましょう。
Webブラウザで動かすには、クラシックWeb(従来のWeb化の方法で、フォームやページを使って行うものですね)とXPagesを使う方法があります。

さきにクラシックWebで行ってみます。
クラシックWebの場合、Notesクライアント用に作成したNotes DBでも改修をしなくてもそこそこ動いてくれるのがいいところですね。
なので、ビューをそのままWebブラウザで表示して、@Command([Compose];"フォーム名")のアクションを実行してみました。

結果はこちら・・・
WebブラウザでのComposeコマンド実行

なんと、エラーになりました!
素晴らしい!ちゃんと「フォームで文書を作成できるユーザー」に設定されている内容を認識するようです。
ただ、エラーメッセージが分かりにくいですね。「アクセスが認証されていません。」だとログインそのものに失敗したのかな?とか変な心配をしてしまいそうです。
ちなみに、設定されているユーザーの場合は、Webブラウザでも新規に文書が作成できました
少なくとも、本来作成できてはいけない文書が作成されるという事はなさそうですね。


3.XPagesの場合はどうなる?

では、つぎにXPagesで試してみましょう。
XPagesの場合、文書を作成するためのページを開いて、そのページの中で「データソース」をバインドするというちょっとやり方になります。

まず、文書を作成するためのページを開くために、ビューページで次のようなアクションを作成しました。
指定したページを開く
このアクションを実行したところ・・・
見事にページが開いてしまいました。
文書を作成するためのページ
NotesクライアントやクラシックWebでは、そもそもこの段階まで進むことができませんでしたので、すでに動きが違うことが分かります。
でも、文書が保存できなければOKですよね。

ではフィールドに値を入力して、保存してみます。
保存にはシンプルアクションの「文書の保存」を選択しました。
現在の文書を保存するというシンプルアクション

結果は・・・保存できちゃいました。
XPagesだと文書が保存できちゃう・・・
あれ?あれれ?
ダメじゃん!XPages!ちゃんと「フォームで文書を作成できるユーザー」を見てよ!困るじゃん!

はい、そういうことで、XPagesの場合は、どうやらバックエンドで文書を作成しているのと同じような動きをしているようです。
これは困りましたね。


4.制御の仕方を考えてみよう

ということなので、やはり「フォームで文書を作成できるユーザー」の値が取得できる必要がありそうです。
では、どうやったら取得できるのでしょうか?
この値はフォームそのものに影響を与えるということは前回の記事の中で紹介しています。
ということは、フォームの情報を取得できれば良さそうだということが考えられます。
IBM Notes/DominoのLotusScriptクラスにはNotesFormというクラスが用意されていますので、そちらを確認してみます。
FormUsersというプロパティがあります。どうやらこれで取得できるのではないでしょうか?
FormUsersプロパティの説明

そこで以下のようなプログラムを作成してみました。
Sub Click(Source As Button)
    On Error Goto ErrProc
    
    Dim session As New NotesSession
    Dim db      As     NotesDatabase
    Dim form    As     NotesForm
    Dim ret     As     String
    
    Set db   = session.CurrentDatabase
    Set form = db.GetForm( "メイントピック" )
    
    ret = "【フォームで文書を作成できるユーザーの一覧】"
    Forall x In form.FormUsers
        ret = ret & Chr$(10) & x
    End Forall
    Msgbox ret, 0 + 64, "FormUsersの確認"
    
    Exit Sub
ErrProc:
    Msgbox _
    "エラー行数:" & Cstr(Erl) & Chr$(10) & _
    "エラー番号:" & Cstr(Err) & Chr$(10) & _
    "エラー内容:" & Error, _
    0 + 16, "FormUsersの確認"
    
    Exit Sub
End Sub

実行した結果は下図の通り。
実行結果

確かに取得できているようです。
あとは、実行しているユーザーがこのユーザー(及びグループ)に合致しているかどうか(グループの場合メンバーかどうか)を確認して文書の作成を許可するかどうかを決めればよいでしょう。

XPagesの場合、LotusScriptではなく、SSJSになりますが、SSJSにもNotesFormクラスがあります(getFormUsers()で取得できます)ので、同じように制御することができるでしょう。


5.まとめ

なかなか難しい話になってしまいましたが、いかがでしたか?
フォームのアクセス権についてはヘルプでもさらっと書いてあっておしまい。なので、なかなか詳細を理解している人は少ないのではないかと思います。
かく言う私も今回色々と調べて分かったことがたくさんありました。

分からないことが起きたら、慌てずにどういうことが起きているのか、本当ならどうなっているべきなのか等々、整理しましょう。
そこから、解決への糸口が見つかるかもしれません。
他の人に質問するにしても、問題が整理されていれば、相手もどこから調べていけばいいのかすぐにわかります。
いちいち整理している暇なんてないよ!すぐにできなければ困るんだ!
という場合であっても、結局はきちんと整理してから調査した方が早いということは多々あります。


今回の場合は、NotesFormクラスのFormUsersプロパティを使うことで、誰がこのフォームで文書を作成してよいのかどうかが分かることが理解できていただければOKでしょう。



それでは今日はこの辺で・・・


Notes/Dominoで困ったことがあれば、弊社にお問い合わせください。
IBM Championの私が承ります!
お問い合わせはこちらから→Lotus Notes/Domino カスタマイズとセキュリティ強化 - 株式会社エフ

フォームのアクセス権について

皆さん、こんにちは。
もうすぐ1月も終わろうというのに、気がかりなことがあります。
それは・・・
2018年度のIBM Championsの正式なアナウンスがまだされてない!ということです。

例年であれば、12月中には発表されるのですが、2018年度のIBM Championsの発表は翌年の1月になりますよ。という通知が来たので、「年越しかぁ、嫌だなぁ」と思っていました。
なかなか発表されないなぁ。と思っていたら、
2018年1月12日 17:10過ぎに、メールが届きました!!
You're a 2018 IBM Champion!

わーい\(^o^)/ って、正式アナウンスは???
いつも、正式アナウンスがあってメールが来るじゃないか!?
ということで、正式アナウンスが行われる(はず)のブログ(IBM Champion Program News and Views)をチェックしてみました・・・

あれ???載ってない。どういうこと???

どうも、今回は全ブランドのIBM Championを一斉に発表しようとしているらしく、その作業に追われているようで、遅れている模様です。
うーん・・・全ブランドのIBM Championって何人くらいなんだろうか?ICS関連だけで百数十名ですから、600名近くになるのかな?それを一斉に発表って、そりゃぁ時間もかかるでしょう。

ということで、正式アナウンスはまだ(2018/01/27現在)ですが、そのうちされると思いますので、気長に待ちましょう。


さて、雑談はこれくらいにしておいて(長いな・・・)、本題に入りましょう。

今回はフォームのアクセス権について調べてみました。

1.アクセス権とは何?

フォームのアクセス権について触れる前に、Notes文書のアクセス権について触れてみます。
IBM Notesでは文書のアクセス権というのはよく聞くと思います。
「読者フィールド」に設定してあるユーザーしか、その文書を読むことができない、また、「作成者フィールド」に設定してあるユーザーしか、その文書を編集することができない(ACLのレベルが"作成者"の場合のみ)というものですね。
ただし、正確に言うと若干違います。
「フィールド」はフォームに設定してあるものです。文書が持つものは「フィールド」ではなく、「アイテム」です。
文書をコピーして、別のNotes DBに貼り付けたとします。
貼り付けた先のNotes DBに「読者フィールド」がなくても「読者」のアイテムに設定されている人しかその文書を読むことができないですよね。
つまり、文書のアクセス権とは文書ごとに設定されるものであるということです。

2.フォームのアクセス権て何?

では、フォームのアクセス権とは何でしょうか?
実際にはそういった用語はなさそうなので、ここでは私が理解していることを伝えていきます。
下の図は、Domino Designerで開いたときの「フォーム」のプロパティです。
一番右の「セキュリティ」タブ(一番右側)を開いたときの状態です。
フォームのアクセス権
ここを見ると、「フォームで作成した文書のデフォルトのアクセス権」という項目と「フォームで文書を作成できるユーザー」という項目があります。

文書のアクセス権と同じように考えると、
フォームで作成した文書のデフォルトのアクセス権」は、文書のアクセス権のデフォルト値を設定する。
フォームで文書を作成できるユーザー」は、文書を作成できるユーザーを設定する。
となりそうです。
さて、実際のところはどうなんでしょうか?



ということで、百聞は一見に如かず!ということで試してみましょう。


3.フォームのアクセス権を設定してみよう(1)

まず、「フォームで作成した文書のデフォルトのアクセス権」について設定しましょう。
Domino Designerでフォームを作成します。
その後、フォームのプロパティの「セキュリティ」タブを開きます。
"読者以上すべて"のチェックを外すと、下の選択肢がアクティブになるので、リストの中から設定したいユーザーにチェックを付けます。
このリストに表示されているのは、Notes DBのACLエントリ及びロールです。そこにないユーザー/グループを設定する場合は、右側にある人の形をしたアイコンをクリックして、ドミノディレクトリから設定することも可能です。
フォームで作成した文書のデフォルトのアクセス権
今回は、図に見えている3つのユーザー/グループを設定しました。
これでフォームを保存して、実際に文書を作成・保存してみました。
なお、比較のために、「フォームで作成した文書のデフォルトのアクセス権」を変更する前の状態で文書を作成してあります。

その結果が、こちらです。

比較してみたところ、設定変更後の文書には「$Readers」というアイテムが余分に作成されていました。
アイテムの属性や値は下図の通りです。
$Readersアイテムがある

 属性(フィールドフラグ)は、"SUMMARY READ-ACCESS"となっています。これは「読者」を表しています。値は、上の「フォーム」で設定したものと一致しています。
つまり、この文書はここに設定してあるユーザー及びグループのメンバーのみ読むことができるという事になります。
 デフォルトの状態("読者以上全て"になっている)で文書を作成した場合、この「$Readers」というアイテムは文書には作成されません。
これは誰も文書を読むことができないというわけではなく、このNotes DBに読者以上のアクセス権を与えられているユーザは全員、読むことができるという事です。


4.フォームのアクセス権を設定してみよう(2)

つぎに「フォームで文書を作成できるユーザー」を設定します。動きを分かり易くするために、「フォームで作成した文書のデフォルトのアクセス権」の値はデフォルト値に戻しておきます。
フォームで文書を作成できるユーザー
設定した値は「LocalDomainAdmins」というグループにしました。私のDomino環境の中で管理者ユーザ―として設定しているグループです。
これでフォームを保存してみました。

さて、どうなるでしょうか?
まずは、管理者グループに含まれるユーザーで見てみます。
文書を作成できるということで、[作成]メニューに表示されるかどうかを確認してみました。
・・・無事に表示されています。
[作成]メニューに表示されている

ここから文書を作成して保存してみましたが、デフォルトの設定で作成したものと変わりはありませんでした。

では、次に設定されていないユーザー(ACLでは「作成者」権限を付与してある)で試してみました。
先ほどと同じように、[作成]メニューから文書を作成しようと・・・
あれ?メニューに表示されてないぞ!?
[作成]メニューに表示されない!?

はい。その通りです。
「フォームで文書を作成できるユーザー」ですから、そこに設定されていないユーザーは、新規に文書を作成することができないのです。

つまり、この「フォームで文書を作成できるユーザー」という設定は、文書に影響を与えるものではなく、フォームそのものに影響を与えるものなのです。

しかし、ここで諦める(?)にはまだ早いです!


5.@関数で文書の作成はできないのか?

はい。IBM Notesには@Command([Compose];"フォーム名")というコマンドがあります。
これを使えば、[作成]メニューからでなくても文書を作成することができます。
これをNotes DBに設定してみて、そこから文書を作成することができるかどうか試してみました。
その結果がこちら・・・
Composeコマンドで試みたが・・・
あえなく撃沈しました(笑)
まぁ、当たり前ですよね。作成できるリストに入ってないのですから。IBM Notesからすれば、「何やってんだよ!作成させないって言ってんだろ!」というところでしょうか。


しかし!我々にはまだLotusScriptという武器があります(笑)

6.LotusScriptだったら?

LotusScriptで新規文書を作成する場合、NotesUIWorkspaceクラスのComposeDocumentメソッドを使用します。
サンプルは当ブログの文書の作成に出ていますので、そちらを参照ください。
ということで、プログラムを作成して実行してみました。

結果は・・・
Composeコマンドの時と同じエラーで撃沈しました(笑)
まぁ、同じことをやっているので、この結果は想定できていました。
IBM Notesも「懲りないやつだなぁ」と思っていることでしょう。

いや、まだだ!
LotusScriptにはバックエンドクラスというものがある!
そうだ、バックエンドで文書を作成したらどうなるんだ!?

ということでやってみました(笑)
ソースはこんな感じです。
Sub Click(Source As Button)
    On Error Goto ErrProc
    
    Dim session As New NotesSession
    Dim db      As     NotesDatabase
    Dim doc     As     NotesDocument
    Dim uiws    As New NotesUIWorkspace
    
    Set db  = session.CurrentDatabase
    Set doc = db.CreateDocument
    Call doc.ReplaceItemValue( "Form", "fsMain" )
    Call doc.ReplaceItemValue( "Subject", "バックエンドで文書を作成" )
    Call doc.ReplaceItemValue( "Categories", "LotusScript" )
    
    Call doc.ComputeWithForm( True, True )
    Call doc.Save( True, True, True )
    
    Call uiws.ViewRefresh()
    Exit Sub
ErrProc:
    Msgbox _
    "エラー行数:" & Cstr(Erl) & Chr$(10) & _
    "エラー番号:" & Cstr(Err) & Chr$(10) & _
    "エラー内容:" & Error, _
    0 + 16, "バックエンドで文書を作成"
    
    Exit Sub
End Sub



あえて、NotesDocumentクラスのComputeWithFormメソッドを使ってフォームで再計算させるようにしています。

で、実行してみました。
結果がこちら。
バックエンドで文書を作成したら・・・


えーっと・・・
作成できてしまいました(笑)
惜しい、惜しいぞ!
正直、ComputeWithFormを実行した段階で、「アクセス権がありません」というエラーが出るのを予想していたのですが、見事にスルー!

うーん・・・どうなんでしょうね。
まぁ、フォームの画面を見ながら作成するわけではないので、思ったように文書を作成するのは難しいということで、良しとしましょう(笑)



7.まとめ

今回は、フォームの「フォームで作成した文書のデフォルトのアクセス権」という項目と「フォームで文書を作成できるユーザー」について調べてみました。
両方とも、Domino Designerで見たときのフォームのプロパティであるにも関わらず、片方は作成された文書に影響するものですが、もう片方はフォームそのものに影響を与えるという、同じ括りにするにはちょっと違和感があるようなものでした。

これらのプロパティの意味が分かってくれれば、今回の記事を書いた意義があるというものです。
さて、次回の予告ですが、 「フォームで文書を作成できるユーザー」の情報をLotusScriptで取得できないものかどうかを確認してみます。
(本当はこれを書きたかったけど、持っていきかたを間違えた・・・orz)





それでは今日はこの辺で・・・




Notes/Dominoで困ったことがあれば、弊社にお問い合わせください。
IBM Championの私が承ります!
お問い合わせはこちらから→Lotus Notes/Domino カスタマイズとセキュリティ強化 - 株式会社エフ

2018年1月1日月曜日

JavaScriptによるイベントの確認

新年、明けましておめでとうございます。


さて、ということで、どこかの誰かさんが「新年のブログまだですか?」とか言うので、書いてやろうじゃないか!と思ったので書いてやる次第です(笑)
新年になって早々・・・

内容は、昨日書いた
LotusScriptによるイベントの確認
に対して、JavaScriptによるフィールドイベントの確認についてです。

JavaScriptはNotesクライアントでも動きますが、LotusScriptで書いた方が楽ですから、
ここではWebクライアントおよびXPagesでの動作について書いていきます。

検証に使用するNotes DBも昨日と同じものを利用します。


1.クラシックWebの場合
クラシックWebでのフィールドイベントを設定する方法は、Notesクライアントとほぼ同じです。
フォームのフィールドを選択して、「OnChange」「OnBlur」イベントに記述するだけです。
WebでのonChangeイベント
「実行」の個所を"Web"、"JavaScript"にして、コードを記述すればOKです。
上の例は「fldText」というテキストフィールドの「onChange」イベントに記述しています。
コードの内容はWebブラウザのコンソールログにメッセージを表示するものです。
すでにNotesクライアント用のコードが記述してあるので、左側のところが上下の二色になっています。
同じように「onBlur」イベントにもコードを記述してみました。
設定自体は簡単ですね。

実行してみた結果がこちらです。
コンソールログへの表示なので、Webブラウザで「F12」キーを押してデバッグモードにしています。
クラシックWebでの実行結果

画面下部の赤枠部分を見てください。
Notesクライアントの場合、OnBlurイベントが発生してからOnChangeイベントが発生していましたが、
WebではonChangeイベントが先に発生しています。
NotesクライアントをWeb化しようとする場合、ここでは注意が必要という事ですね。

では、XPagesの場合はどうでしょう?

2.XPagesの場合
XPagesの場合、フォームに設定・・・はできませんので、XPage画面を作成してその中で設定します。
下図のような画面を作成して、イベントにコードを記述してみました。
XPagesのCSJSでイベントチェック

編集ボックスコントロールを配置して、そのonblurイベントにCSJS(クライアントサイドのJavaScript)を記述してみました。コードの内容は先ほどのクラシックWebのものと同じです。
同様にonchangeイベントにも記述してあります。
実行結果は下図です。
CSJSでのイベント確認の実行結果

クラシックWebの時と同じようにテキストフィールドに値を入力して、他のフィールドに移動してみたところ、
onchangeイベントが発生してからonblurイベントが発生しました。
Web系ではonchangeが先に発生するようですね。


XPagesの場合、CSJSだけでなく、SSJS(サーバーサイドJavaScript)での記述もできます。
こちらは少し面白い結果が出ました。

SSJSの場合、Dominoサーバーにイベントが送られるので、「サーバーオプション」を"更新なし"以外にする必要があります。
SSJSでのイベントチェック

実行結果は次の通りです。
SSJSでの実行結果

SSJSの場合、onchangeイベントはフィールドから移動しなくても発生します。
サーバーに随時値を送っているからだと思われます。
上の図で時間が少し開いているのは、値の変更後、すぐにフィールドを抜け出てしまうと、onblurイベントがなぜか発生しなくなるからです。
これもサーバーで処理をしている関係なのでしょうか?


さらに、SSJSとCSJSの両方にonblur、onchangeイベントを記述しておくと、onblurとonchangeが同時に発生しても、CSJSのonblurも実行されなくなります(フィールドの値を変更すると、onchangeしか発生しない。フィールドの値を変更しないでフィールドから外れるとonblurは発生する)。

細かい検証をしたわけではないので、正しく動いてくれているかどうかは不明ですが、実装する際は気を付けてみてください。






それでは今日はこの辺で。
今年も当ブログをよろしくお願いいたします。


Notes/Dominoで困ったことがあれば、弊社にお問い合わせください。
IBM Championの私が承ります!
お問い合わせはこちらから→Lotus Notes/Domino カスタマイズとセキュリティ強化 - 株式会社エフ