プリザンターのアクセス制御について改めて整理してみる

# はじめに
みなさんこんにちは。プリザンター使ってますか？
ある程度使えるようになってきたり、業務で使用していると「グループによって権限を分けたいな～」や「自分のレコードだけ表示させたいな～」などアクセス制御系の悩みが出てきます。
ただ、アクセス制御ってやれることが多くて何をどう設定すれば思い通りになるのかわからない....そんな経験はないでしょうか？
ということで、今回はよく悩みがちなアクセス制御についてまとめてみました。

# アクセス制御について
プリザンターでアクセス制御を行う方法は大きく分けて下記の３つに分類されます。
- パラメータファイルによる設定変更
- 標準機能によるアクセス制御
- サーバスクリプト：Viewによるアクセス制御
以降はこれらの設定方法と種類、どういったケースで有効なのかについてまとめていきます。

## パラメータファイルによる設定変更
パラメータファイルによる設定の変更を行った場合、特定のテーブルやサイトに対してのアクセス制御ではなくプリザンター全体に対して影響が及びます。

### Permissions.json
[パラメータ設定：Permissions.json | Pleasanter](https://pleasanter.org/ja/manual/permissions-json)
Permissions.jsonは、後述する標準機能によるアクセス制御を行う際の既定値やアクセス権設定対象一覧に表示するリストの最大件数の変更が可能です。
設定可能なアクセス権の数字は、下記のソースコードのenum Typesに記載されている数値の論理和です。
https://github.com/Implem/Implem.Pleasanter/blob/master/Implem.Pleasanter/Libraries/Security/Permissions.cs

### Site.json
[パラメータ設定：Site.json | Pleasanter](https://pleasanter.org/ja/manual/site-json)
Site.jsonはトップ画面のサイトの並べ替えを実行できるユーザを変更します。
任意のユーザIDもしくは「0」を指定することができ、「0」を指定した場合はすべてのユーザがトップの配置を変更可能になります。
また、ユーザIDを指定した場合でも「特権ユーザ」は並び替えを行うことが可能です。

### User.json
[パラメータ設定：User.json | Pleasanter](https://pleasanter.org/ja/manual/user-json)
User.jsonはユーザごとに既定の権限を設定し、管理者が許可をしていくような運用をする場合に有用です。
トップサイトへのサイト作成や、グループの管理/作成、APIの使用制限などを管理者が対象のユーザ管理画面でチェックを有効化することで使用可能になります。

### Security.json
[パラメータ設定：Security.json | Pleasanter](https://pleasanter.org/ja/manual/security-json)
Security.jsonではプリザンターそのものに対するアクセス制御をIPアドレス単位で設定することが可能です。
また、特権ユーザを設定することが可能です。

### 特権ユーザ
[ユーザ管理機能：特権ユーザの設定 | Pleasanter](https://pleasanter.org/ja/manual/user-management-privileged-users)
「特権ユーザ」はプリザンターの権限設定に関わらず、全てのリソースに対して全ての権限を有する特別なユーザです。
「テナント管理者」とは別の権限であり、初期設定では「特権ユーザ」は存在しません。
特権ユーザ以下の特徴があります。
- アクセス権のないサイトにアクセスが可能
- ユーザをスイッチすることが可能
- トップのゴミ箱が操作が可能
- プリザンター上でシステムログを表示することが可能
- 自分でロックしていないテーブルのロックの解除が可能
- 自分でロックしていないレコードのロックの解除が可能
- ユーザ招待機能を使用した際のユーザの承認が可能
- バージョン管理画面にDB使用量を表示が可能
- プリザンターを再起動せずにParametersフォルダ配下の情報を再読み込みが可能
- バックグラウンドサーバスクリプトの設定が可能

:::note warn
注意
特権ユーザの本質は「アクセス制御無視する」ことにあります。
したがって特定のユーザに対して、読取専用にするようなアクセス制御を行った場合、特権ユーザも読取専用となってしまうことには注意が必要です。
:::

## 標準機能によるアクセス制御
標準機能によるアクセス制御では対象となるフォルダ/テーブル/レコードに対して、組織/グループ/ユーザ単位で決まったアクセス権の付与をすることが可能です。
[サイト機能：アクセス制御 | Pleasanter](https://pleasanter.org/ja/manual/site-access-control)

## サイトのアクセス制御
### アクセス制御の対象
|No|対象|説明|
|:--:|:--|:--|
|1|フォルダ|フォルダにアクセス権を設定することで、その配下のテーブルなどにアクセス権を継承できます|
|2|期限付きテーブル|テーブルおよびテーブル内のレコードのアクセス権を設定できます|
|3|記録テーブル|テーブルおよびテーブル内のレコードのアクセス権を設定できます|
|4|Wiki|Wikiのアクセス権を設定できます|
|5|ダッシュボード|ダッシュボードのアクセス権を設定できます|

### アクセス制御の設定単位
|No|単位|説明|
|:--:|:--|:--|
|1|組織|組織に所属するユーザに対してまとめてアクセス権を付与します|
|2|グループ|グループに所属するユーザに対してまとめてアクセス権を付与します|
|3|ユーザ|一人のユーザにアクセス権を付与します|

### アクセス制御できる権限一覧
|No|種類|説明|
|:--:|:--|:--|
|1|読取り|テーブルのレコードやWikiの表示|
|2|作成|テーブルのレコードの新規作成|
|3|更新|テーブルのレコードやWikiの更新|
|4|削除|テーブルのレコードやWikiの削除|
|5|メール送信|テーブルのレコードやWikiからメールを送信|
|6|エクスポート|テーブルのレコードをCSVファイルとして出力|
|7|インポート|CSVファイルのデータをテーブルにインポート|
|8|サイトの管理|サイトの作成、設定の変更、削除、サイトの移動、並び替え|
|9|権限の管理|サイトやレコードの権限を設定|

### サイト作成時のアクセス設定について
トップにサイトを作成した場合、「サイトの作成者」に対してのみアクセス権が付与されます。
他のユーザに表示させるためには対象となるユーザにアクセス権を与える必要があります。
2階層目以降にサイトを作成した場合、1階層目の権限設定を継承します。
テーブルの管理から、サイトのアクセス制御タブを選択し、「アクセス権の継承」を「アクセス権を継承しない」に設定することで独自のアクセス権限を付与することが可能です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3551590/c8dbe885-ed7c-8e71-6ba9-ba7d15a6a68f.png)

## レコードのアクセス制御
[テーブル機能：レコードのアクセス制御 | Pleasanter](https://pleasanter.org/ja/manual/table-record-access-control)
テーブルの「レコード」に「アクセス権」を設定する事ができます。

:::note warn
注意
「レコードのアクセス制御」では「レコード」1件1件に権限の設定を行う必要があります。特定の条件で一覧画面に表示するレコードを絞り込みたいケースではサーバスクリプトの「view.Filtersオブジェクト」または拡張SQLのOnSelectingWhereを使用してください。
:::

サイトのアクセス制御で「アクセス権」を割り当てられていないユーザにも特定のレコードに対してのみ「アクセス権」を付与することができます。
上記場合、サイトのアクセス権限がないため、トップや上位フォルダにはサイトは表示されませんが、レコードのアクセス権限は付与されているためURLを直接入力することで遷移が可能です。

サイトのアクセス制御と「レコードのアクセス制御」を同時に設定した場合には、両方の「アクセス権」が有効になります。
例えばサイトのアクセス制御で「読み取り権限」を付与し「レコードのアクセス制御」で「更新権限」を付与した場合には、「読み取り権限」と「更新権限」の両方が有効になります。

__アクセス権限の組み合わせによる違い__
サイト：読み取り専用
レコード：設定なし
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3551590/489ab4a5-84aa-38af-f515-ccfc23e96c3a.png)
サイト：読み取り専用
レコード：書き込み権限あり
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3551590/1c6feb2a-691d-3b93-a234-fe476cd4445f.png)

### レコードのアクセス制御を項目に応じて設定する
テーブルの管理からレコードのアクセス制御タブを開き、選択肢一覧から項目を選択すると、レコードの該当項目に設定されたユーザに対してレコードの権限が付与されます。
初期設定では管理者と担当者のみですが、分類項目も指定可能です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3551590/a1e92a21-5b33-842d-cc3f-d3de04a55e44.png)

設定内容は下記の表を参考にしてください。
|No|選択肢|説明|
|:----|:----|:----|
|1|[組織]|「レコード」を作成・更新した「ユーザ」が所属する「組織」に指定した「アクセス権」が付与されます。|
|2|[グループ]|「レコード」を作成・更新した「ユーザ」が所属する「グループ」に指定した「アクセス権」が付与されます。|
|3|[ユーザ]|「レコード」を作成・更新した「ユーザ」に指定した「アクセス権」が付与されます。|
|4|[項目]管理者|新規作成・更新する「レコード」の「管理者項目」に指定した「ユーザ」に「アクセス権」が付与されます。|
|5|[項目]担当者|新規作成・更新する「レコード」の「担当者項目」に指定した「ユーザ」に「アクセス権」が付与されます。|
|6|[項目]分類|新規作成・更新する「レコード」の「分類項目」に指定した任意の「ユーザ」、「組織」、「グループ」に「アクセス権」が付与されます。

## 項目のアクセス制御
項目のアクセス制御では、各項目のアクセス制御（「作成権限」、「読み取り権限」、「更新権限」）を行うことが可能です。

### 作成時のアクセス制御
アクセス権を持たない利用者が「レコード」の新規作成を行うとエディタ上で該当の項目が読取専用となります。

### 読取り時のアクセス制御
アクセス権を持たない利用者が「レコード」の一覧画面やエディタを開いた際に、対象の項目が非表示となります。

### 更新時のアクセス制御
アクセス権を持たない利用者が「レコード」のエディタを開いた際に、対象の項目が読取専用となります。

### その他タブ
項目のアクセス制御では特定のユーザやグループでの許可のほかに「必要なアクセス許可」や「許可するユーザ」を設定することが可能です。

- 必要なアクセス許可
対象の「レコード」に対してチェックした権限を持っているユーザにアクセスを許可します。
例えば「読取り時のアクセス制御」のその他タブで「サイトの管理」にチェックした場合、「サイトの管理権限」をもっているユーザにのみ項目を表示します。

- 許可するユーザ
対象の「レコード」のチェックした項目にログインユーザが設定されている場合にアクセスを許可します。
例えば「更新時のアクセス制御」のその他タブで「担当者」にチェックした場合、ログインユーザが「担当者」にセットされているレコードのみ項目が更新可能になります。
それ以外の場合には読取専用で表示します。「管理者」と「担当者」など複数のチェックを入れた場合には、いずれかに該当した場合にアクセスを許可します。

## サーバスクリプト：Viewによるアクセス制御
ここまでのアクセス制御はある程度決まった型に収まった場合に効力を発揮するアクセス制御です。
Viewによるアクセス制御を行うことで、「特定のグループに初速しているユーザ」など動的に権限が変わるケースに対して有効な制御を行うことが可能です。
[開発者向け機能：サーバスクリプト：view | Pleasanter](https://pleasanter.org/ja/manual/server-script-view)

### view.Filters 
[開発者向け機能：サーバスクリプト：view.Filters | Pleasanter](https://pleasanter.org/ja/manual/server-script-view-filters)
一覧画面やエディタに表示するレコードをフィルタすることで、ユーザに閲覧させるレコードを制限することができます。
レコードのアクセス制御と異なり「レコード」1件1件にアクセス権を設定する必要がありません。
設定には[開発者向け機能：JSONデータレイアウト：View | Pleasanter](
https://pleasanter.org/ja/manual/api-view)が使用できます。
例えば、分類Aは選択肢となっていて、「全体向け」と「社内向け」が選択できるとします。
「全体向け」のレコードは誰でも閲覧できますが、「社内向け」となっているレコードは一部のユーザにのみ閲覧許可をしたい場合、下記のようなサーバスクリプトを記述することでレコードの分類Aに応じて動的にアクセス制御を行うことが可能です。
```javascript
//条件：ビュー処理時
if (context.DeptId  != 1){
    view.Filters.ClassA = '["全体向け"]'
} else {
    view.Filters.ClassA = '[]'
}
```
このサーバスクリプトは、組織ID：１に所属していないユーザに対して全体向けのレコードのみ表示するように設定します。
逆に、組織ID：１に所属しているユーザに対してはすべてのレコードを表示します。
組織ID：1に所属しているユーザがアクセスした場合
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3551590/16050bcf-3e60-b3bd-6824-6985aa4448cb.png)
組織ID：1に所属していないユーザがアクセスした場合
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3551590/508c2f48-7afe-e065-58c6-6452d788980f.png)

### view.OnSelectingWhere
さらに複雑な絞り込みを行う場合は、OnSelectingWhereは拡張SQLを使用します。
[開発者向け機能：拡張機能：拡張SQL | Pleasanter](https://pleasanter.org/ja/manual/extended-sql)
[FAQ：一覧表示するレコードを所属組織別に分けたい | Pleasanter](https://pleasanter.org/ja/manual/faq-extended-sql-selecting-where)
拡張SQLの設定方法は上記マニュアルを確認してください。

拡張SQLを設定した環境で、下記のようなサーバスクリプトを設定します。
```javascript
//サーバスクリプトに設定するjavascript
if (context.DeptId !== 3) {
    view.Filters.OnSelectingWhere = 'SelectingWhereName';
}
```
```jsonc
//.¥Pleasanter¥App_Data¥Parameters¥ExtendedSqls¥ 配下に格納するjson
{
    "Name": "SelectingWhereName",
    "SpecifyByName": true,
    "OnSelectingWhere": true,
    "CommandText": "([Issues].[Status]=900)"
}
```
上記サンプルは組織ID：３に所属していないユーザに対して、jsonに記載したSQLを適用します。

# おわりに
プリザンターのアクセス制御はかなり奥が深いです。
基礎知識としてJavaScriptやSQLの知識が必要にはなりますが、サーバスクリプトや拡張SQLを使用することで、ここに上げたサンプル以上に複雑な条件でアクセス権を行うことが可能です。
JavaScriptやSQLを使うのが難しいという方も、前半で説明した標準機能によるアクセス制御だけでもかなりのケースに対応できると思います。
アクセス制御の設定に困った際は、この記事をチートシートとして運用していただけると幸いです。