レコードの権限
Related information
はじめに
レコード権限 DSL (ドメイン固有言語) を使用して、特定のテーブルのレコードに対するアクセスルールを指定します。
レコード権限 DSL の主な目的は、Java コーディングを必要とせず、プログラミングの深い知識がない人でも簡単に使用できるようにすることです。
スクリプトを使用して、任意のテーブルに対する権限を指定できます。スクリプトは、レコードの権限を示す一連の if then else および return ステートメントで構成されます。
データモデルアシスタント (DMA) を使用してスクリプトを編集できます。
字句構造
はじめに
スクリプトの構造は次のとおりです。
begin
<statement 1>
<statement 2>
...
<last statement>
end
最後のステートメントを除くすべてのステートメントは、「if then」または「if then else」ステートメントにする必要があります。
例
if isMember(administrator) then
// Administrator has no restrictions.
return readWrite;
if isMember('french-team') and record.Country='F' then
//Members of 'french-team' can view and modify data for France.
return readWrite;
if isMember('us-team') and record.Country='US' then
//Members of 'us-team' can view and modify data for US.
return readWrite;
// This statement is not actually needed as 'hidden' is the default permission.
return hidden;
文字セット
Unicode 文字セットがサポートされています。
文字の大文字と小文字の区別
DSL では大文字と小文字が区別されます。
コメント
1 行のコメントは、// から現在の行の終わりまで拡張されます。
// This is a comment
if record.LastName = 'Doe' then // This is another comment.
return readOnly;
複数行のコメントは /* から始まり、*/ で終わります。
/* This is a sample of a multi-line
comment */
if record.isActive then
return readWrite;
キーワード
キーワードには次の 2 種類があります。
-
予約済みキーワード は、if、then、else、begin、end、return、null、and、or、not、true、false、\_ebx です。
-
予約されていないキーワードは、DSL によって定義されている他のすべてのキーワードです。
2 種類のキーワードの主な違いは、予約されていないキーワードは、プレーンな (引用符で囲まれていない) 識別子として使用できることです。
識別子
引用符なしの識別子
引用符で囲まれていない識別子 は、文字、数字、またはアンダースコア ( \_ ) の長さ無制限のシーケンスです。最初の文字は文字にする必要があります。
有効な文字は a から z および A から Z です。有効な数字は 0 から 9 です。
引用符で囲まれていない識別子は、予約済みのキーワードと同じにすることはできません。
引用符付きの識別子
引用符で囲まれた識別子は、Unicode 文字の長さに制限はありません。
引用符で囲まれた識別子は、二重引用符で囲んで使用する必要があります。
引用符で囲まれていない識別子は、二重引用符で囲んで使用できます。つまり、識別子 ”a\_name" は a\_name と等しいということです。
引用符で囲まれた識別子は、 "\_ebx" を除く予約キーワードにすることができます。
型
サポートされている型
次の型がサポートされています。
| タイプ | EBX® 対応型 |
|---|---|
| Boolean | xs:boolean |
| 10 進数 | xs:decimal xs:int xs:integer |
| String | xs:string xs:anyURI xs:Name osd:text osd:html osd:email osd:password osd:color osd:resource osd:locale osd:dataspaceKey osd:datasetName |
| タイムスタンプ | xs:dateTime |
| Date | xs:date |
| 時間 | xs:time |
リテラル
文字列リテラル
文字列リテラルは、一重引用符で囲まれた Unicode 文字の任意のシーケンスにすることができます。次の表は、エスケープシーケンスで置き換える必要のある文字を示しています。
| 文字 | エスケープシーケンス |
|---|---|
| タブ | \t |
| バックスペース | \b |
| 改行 | \n |
| キャリッジリターン | \r |
| フォームフィード | \f |
| 一重引用符 | \' |
| バックスラッシュ | \\ |
文字は、Unicode 文字の 16 進コード XXXX を使用した \uXXXX 形式の Unicode エスケープシーケンスで指定できます。
例
| 値 | 構文 |
|---|---|
| O’Harra | 'O\'Harra' |
| Noël | 'No\u00EBl' |
| été | '\u00e9\u00E9' |
注意
無効なエスケープまたは Unicode シーケンスは、コンパイル時にエラーを生成します。
10 進リテラル
次の 10 進形式がサポートされています。
| 形式 | 例 |
|---|---|
| Integer | 546 -67 |
| 浮動小数点数 | 54.987 -433.876 0.00054 -0.0032 |
| 指数表記 | 34.654e-5 -45E+65 1.543e23 |
タイムスタンプリテラル
タイムスタンプリテラルの形式は dt(yyyy-MM-dd hh:mm:ss.sss) です。
秒はオプションです。秒が指定されていない場合、0 が想定されます。秒は、ミリ秒の精度までの小数部を持つことができます。
グレゴリオ暦で無効な日付は、コンパイル時にエラーを生成します。
例
dt(2010-01-02 00:00:00.000)
dt(2019-2-3 12:56:7)
dt(2019-2-3 12:56:7.5)
dt(2019-5-7 1:6)
日付リテラル
日付リテラルの形式は d(yyyy-MM-dd) です。
グレゴリオ暦で無効な日付は、コンパイル時にエラーを生成します。
例
d(2010-01-02)
d(2019-2-3)
dt(2019-5-7)
時間リテラル
時間リテラルの形式は t(hh:mm:ss.sss) です。
秒はオプションです。秒が指定されていない場合、0 が想定されます。秒は、ミリ秒の精度までの小数部を持つことができます。
無効な時間は、コンパイル時にエラーを生成します。
例
t(00:00:00)
t(12:56:7)
t(12:56:7.5)
t(1:6)
ブール値リテラル
ブール値リテラルは true と false です。
フィールドアクセス
単純なフィールド
最適化/インデックス付きテーブルフィールドへのアクセスのみがサポートされています。ドット表記は、テーブルフィールドにアクセスするために使用されます。たとえば、パスが ./OfficeAddress/City である現在のテーブルフィールドの条件は次のようになります。
if record.OfficeAddress.City = 'Paris' then
return readWrite;
エイリアス record は、常に現在のレコードを参照します。コンテキストによっては、他のエイリアスが使用できる場合があります。
各ステップ (ドットで区切られた部分) は識別子です。これは、次の引用表記を任意のステップに使用できることを意味します。
if record."OfficeAddress".City = 'Paris' then
return readWrite;
これは、予約済みのキーワードに相当するステップや、マイナス文字 ( - ) やドット ( . ) などの文字を使用するステップに役立ちます。これらは、引用符で囲まれていない識別子と互換性がありません。
実行時に、どのステップも null と評価される可能性があります。この場合、完全なフィールド式は null と評価されます。
外部テーブルフィールド
ドット表記を使用して外部キーを「フォロー」することにより、外部テーブルにアクセスできます。
次の例では、フィールド Supervisor は外部キーです。
if record.Supervisor.Name = 'John Doe' then
return readWrite;
次の例のように、複数レベルの外部キーが存在する場合もあります。
if record.Supervisor.Supervisor.Supervisor.Name = 'John Doe' then
return readOnly;
リスト (複数値) フィールドアクセス
複数値フィールドはサポートされていません。
関連付け
集計関数は、関連付けに基づいて入力式として受け取ることができます。次の例では、フィールド ManagedUsers は関連付けです。
// All users that manage at least 2 persons have read write access.
if count(record.ManagedUsers[]) >= 2 then
return readWrite;
関連付けにフィルターを適用できます。関連付けからフィールドにアクセスするには、エイリアスを使用する必要があります。関連エイリアスは : を使用して宣言されます。次の例では、エイリアスは u1 です。
// All users that manage at least one person whose office is in Briton has read only access.
if exists(record.ManagedUsers:u1[u1.OfficeAddress.City='Briton']) then
return readOnly;
関連付けのフィルターは、現在のレコードのフィールドを参照できます。
// All users that manage at least one person whose office is in the same city as user has read only access.
if exists(record.ManagedUsers:t1[t1.OfficeAddress.City=record.OfficeAddress.City]) then
return readOnly;
関連付けのフィルターには、埋め込み集計関数を含めることができます。
// All users that manage at least one person who manages at least one person has read only access.
if exists(record.ManagedUsers:t1[exists(t1.ManagedUsers[])]) then
return readOnly;
埋め込み集計関数に対する関連付けのフィルターは、現在のレコードのフィールドおよび親関連付けのフィールドを参照できます。
// All users that manage at least one person who manages at least one person whose office is in the same city
// as his/her two first managers in the hierarchy has read only access.
if exists(record.ManagedUsers:t1[exits(t1.ManagedUsers:t2[t2.OfficeAddress.City=record.OfficeAddress.City and t2.OfficeAddress.City=t1.OfficeAddress.City])]) then
return readOnly;
演算子
デフォルトでは、操作の評価順序は優先度と結合性に基づいています。評価の順序は、括弧を使用して明示的に示すことができます。
次の表は、優先度の高いものから低いものへのすべての演算子とそれらの関連性を示しています。
Null 値の管理
算術演算子
算術演算子 ( * 、/ 、+ および - ) は null を返します。オペランドは null です。
比較演算子
比較演算子 ( <、<=、>、=>、= および <> ) は、いずれかのオペランドが null の場合、 null を返します。
ブール演算子
ブール演算子はスレッド値ロジックを使用します。
AND の真偽 (true/false) 表は次のとおりです。
| And | true | false | null |
|---|---|---|---|
| true | true | false | null |
| false | false | false | false |
| null | null | false | null |
OR の真偽 (true/false) 表は次のとおりです。
| Or | true | false | null |
|---|---|---|---|
| true | true | true | true |
| false | true | false | null |
| null | true | null | null |
インデックス式
null と評価されるか範囲外のインデックスを持つインデックス付き式は、 null を返します。
関数
パラメーターが null の場合、関数は通常 null を返します。例外は関数 isNull(value) で、null を返すことはありません。
If ステートメント
「If then」ステートメント
「if then」ステートメントの構文は次のとおりです。
if condition-expression then
then-body-statement
条件式はブール型として評価される必要があります。
式が true と評価された場合、「then」ステートメントが実行されます。式が false または null と評価された場合、「then」ステートメントは無視されます。
「then」ステートメントは body ステートメント です。
「If then else」ステートメント
「if then else」ステートメントの構文は次のとおりです。
if condition-expression then
then-body-statement
else
else-body-statement
条件式はブール型にする必要があります。
式が true と評価された場合、「then」ステートメントが実行されます。式が false または null と評価された場合、「else」ステートメントが実行されます。
「then」または「else」ステートメントは body ステートメント です。
注意
式
if condition-expression then
statement-a;
else
statement-b;
上記の式は、以下の式とは同等ではない可能性があります。
if not condition-expression then
statement-b;
else
statement-a;
実際、式が null の場合、どちらの場合も「else」ステートメントが実行されます。
「Then」または「else」の本文ステートメント
本文のステートメントは次のようになります。
-
「if then」または「if then else」ステートメント
-
ステートメントブロック
ステートメントブロックは、複数のステートメントをグループ化するために使用されます。キーワード begin で始まり、キーワード end で終わります。
begin
<statement 1>
<statement 2>
...
<last statement>
end
最後のステートメントを除くすべてのステートメントは、「if then」または「if then else」ステートメントにする必要があります。
if isMember('sales-team')then
begin
if record.Country='F' then
return readWrite;
if record.Country='UK' then
return readOnly;
end
else
begin
if record.Country='D' then
return readOnly;
if record.Country='B' then
return readWrite;
return hidden;
end
return ステートメント
return ステートメントは、特定の条件を満たすレコードへのアクセスを指定します。
次の表に、有効な return ステートメントを示します。
| return ステートメント | 説明 |
|---|---|
| return hidden; | レコードは非表示になっています (ユーザーにはアクセス権がありません)。 |
| return readOnly; | レコードは、現在のユーザーに対してのみ読み取られます。 |
| return readWrite; | レコードは、現在のユーザーが読み取って変更できます。 |
特定のレコードに適用される return ステートメントがない場合、値 hidden が想定されます。
コンテキスト変数
はじめに
レコードの権限は、現在のデータスペース、データセット、またはセッションによって異なります。
データスペース
事前定義されたエイリアス dataspace は、現在のデータスペースに関する情報へのアクセスを提供します。
このエイリアスは、次のフィールドへのアクセスを提供します。
| 名前 | タイプ | 説明 |
|---|---|---|
| name | string | データスペースの名前。データスペースの名前空間とスナップショットの名前空間は独立しているため、返される文字列は名前空間の 1 つのコンテキストにおける識別子にすぎません。グローバルデータスペースまたはスナップショット識別子には、フィールド id を使用します。 |
| id | string | データスペースまたはスナップショットの永続的な識別子。name と比較すると、この識別子は、この ID がデータスペース用かスナップショット用かをさらに指定します。 |
| isSnapshot | boolean | データスペースがスナップショットの場合は true であり、データスペースがブランチの場合は false です。 |
例
if dataspace.name = 'branch-R' then
return readOnly;
データセット
事前定義されたエイリアス dataset は、現在のデータセットに関する情報へのアクセスを提供します。
このエイリアスには次のフィールドがあります。
| 名前 | タイプ | 説明 |
|---|---|---|
| name | string | データセットの名前 |
例
if dataset.name = 'TEST' then
return readWrite;
セッション
事前定義されたエイリアス session は、現在のユーザーセッションに関する情報へのアクセスを提供します。
このエイリアスには次のフィールドがあります。
| 名前 | タイプ | 説明 |
|---|---|---|
| userId | string | 現在のユーザーの ID |
| userEmail | string | 現在のユーザーのメール |
| trackingInfo | string | 現在のセッションの追跡情報。 |
現在のユーザーのロールを確認するには、ロールを参照してください。
例
if session.userId = 'jdoe' then
return readWrite;
コンテキスト関数
ロール
次の表では、isMember() 関数について説明します。
| 構文 | 説明 |
|---|---|
| isMember(ロール式…) | 現在のユーザーが指定された式から評価されたロールの少なくとも 1 つを持っている場合、true を返します。 ロール式は、ロールリテラルまたはフィールドパスにすることができます。 ロールリテラルに関しては、次のビルトインロールは引用符なしで指定する必要があります。administrator、readOnly、everyone。 カスタムロールは文字列リテラルとして指定されます。存在しないロールを指定してもエラーにはなりません (メンバーのいないロールと見なされます)。 注意 ロール administrator と 'administrator' は 2 つの異なるロールにすることができます。これは、isMember(administrator) が isMember('administrator') と同じ結果を返さない可能性があることを意味します。同じルールが他のビルトインロールにも適用されます。 |
例
// ロールリテラル:
if isMember('SALES', 'SUPPORT') then
return readWrite;
// ロール管理者 (引用符なし):
if isMember(administrator) then
return readOnly;
// フィールドパス:
if isMember(record.AuthorizedRole) then
return readWrite;
// 異なるロール式を同時に使用できます:
if isMember('SALES', 'SUPPORT', administrator, record.AuthorizedRole) then
return readWrite;
テーブルで構成されたロールに権限を依存させるには、1 つまたは複数の関連付けによってレコードに関連付ける必要があります。次に、関数 isMember を次のように使用する必要があります。
// 現在のユーザーに承認されているゾーンに割り当てられているすべてのレコード
// (つまり、ユーザーのロールの少なくとも 1 つが Roles.AuthorizedRole フィールドで構成されている場合)。
if exists(record.Zones:Z[exists(Z.Roles:R[isMember(R.AuthorizedRole)])]) then
return readOnly;
セッション
次の表では、セッション関数について説明します。
| 構文 | 説明 |
|---|---|
| getSessionInputParameter(parameterKey, lookupInParentSessions) | 指定された parameterKey に対応するセッション入力パラメーターを返します。 ワークフローインタラクションのコンテキストでは、関数はワークフロータスクの入力パラメーターでパラメーターを検索します。 lookupInParentSessions が true の場合、関数は親セッションでパラメーターを検索します。 それ以外の場合は、現在のセッションでのみパラメーターを検索します。 |
| isInWorkflowInteraction(lookupInParentSessions) | 現在のセッションがワークフローインタラクションコンテキスト内にある場合は、true を返します。 lookupInParentSessions が true の場合、親セッションがワークフローインタラクションコンテキスト内にある場合、この関数は true を返します。 それ以外の場合、関数は現在のセッションのコンテキストのみを評価します。 |
例
// Give read write access if the scripted rule is called in a workflow interaction context and the 'instance' input parameter for the workflow task is 'Library'.
if isInWorkflowInteraction(true) and getSessionInputParameter('instance', true) = 'Library' then
return readWrite;
その他の関数
文字列照合関数
文字列照合関数は、次の 3 つのパラメーターを取ります。
-
文字列として評価される stringExpression。
-
文字列リテラルの必要がある pattern。
-
照合で大文字と小文字が区別されるかどうかを示すオプションのブールリテラル isCaseSensitive。省略した場合、照合では大文字と小文字が区別されないと見なされます。
| 構文 | 説明 |
|---|---|
| matches(stringExpression, pattern, isCaseSensitive) | stringExpression が Java 正規表現 pattern と一致する場合、true を返します。 |
| startsWith(stringExpression, pattern, isCaseSensitive) | stringExpression が文字列 pattern で始まる場合、true を返します。 |
| endsWith(stringExpression, pattern, isCaseSensitive) | stringExpression が文字列 pattern で終わる場合、true を返します。 |
| contains(stringExpression, pattern, isCaseSensitive) | stringExpression に文字列 pattern が含まれている場合、true を返します。 |
| containsWholeWord(stringExpression, pattern, isCaseSensitive) | stringExpression に単語全体 pattern が含まれている場合、true を返します。 |
例
// Give read write access if first name starts with 'a', 'b' or 'c' (case-sensitive).
if matches(record.FirstName, '[a-c].*', true) then
return readWrite;
// Give read only access if first name starts with 'Lé' (case-insensitive).
if startsWith(record.FirstName, 'Lé') then
return readOnly;
// Give read only access if first name ends with 'my' (case-insensitive).
if endsWith(record.FirstName, 'my') then
return readOnly;
// Give read only access if email contains with 'BeauMont@' (case-sensitive).
if contains(record.Email, 'BeauMont@', true) then
return readOnly;
// Give read write access if last name contains the whole word 'Michel' (case-insensitive).
if containsWholeWord(record.LastName, 'Michel', false) then
return readWrite;
集計関数
次の集計関数は、関連付けで使用できます。
| 構文 | 説明 |
|---|---|
| count(expression) | 式の行数を返します。 |
| exists(expression) | 式が少なくとも 1 行と評価された場合、true を返します。 |
例
// Give read write access if managed users count is at least 2.
if count(record.ManagedUsers[]) >= 2 then
return readWrite;
// Give read only access if count of managed users that are not in Paris is less than 4.
if count(record.ManagedUsers:m1[m1.OfficeAddress.City<>'Paris']) < 4 then
return readOnly;
// Give read write access if managed users count is at least 1.
if exists(record.ManagedUsers[]) then
return readWrite;
// Give read write access if count of managed users that are not in Briton is at least 1.
if exists(record.ManagedUsers:u1[u1.OfficeAddress.City<>'Briton']) then
return readWrite;
日付と時刻の関数
次の表に、日付と時刻の関数を示します。
| 構文 | 説明 |
|---|---|
| datetimeNow() | 現在の日付と時刻を返します。 |
| dateNow() | 現在の日付を返します。 |
| timeNow() | 現在の時刻を返します。 |
例
// Give read write access if the last possible update date hasn't expired yet.
if record.LastPossibleUpdateDate >= dateNow() then
return readWrite;
else
return readOnly;
その他の関数
次の表は、ブール値を返すビルトイン関数についての説明です。
| 構文 | 説明 |
|---|---|
| isNull(value) | 値が null の場合は true を返します。値は、任意のタイプの式にすることができます。 |
例
// Give read write access if no supervisor.
if isNull(record.supervisor) then
return readWrite;