プロジェクト間共用カスタムクエリをadmin以外が作成/編集可能にする

　Redmineでは、プロジェクト間で共用するカスタムクエリの作成及び編集操作は、adminのみ可能である。
　この事は、特に大規模環境でカスタムクエリ機能を活用する上でボトルネックとなり得る。そのため、改善方法を検討し実装した。
Redmine本体のソースを数行修正し、権限設定を行うだけで利用可能である。
以下に実際の構成例、修正箇所を示す。

本件はRedmine本家にチケット起票済です。
賛成の方は本家に一票ください。(コメント最初に +1 )
Allowing non-admin to create/edit custom queries shared among projects
http://www.redmine.org/issues/31349

# 課題

Redmineでは、プロジェクト間で共用するカスタムクエリの作成及び編集操作は、adminのみ可能である。

この事は、結果的に下記問題を招く場合がある（特に大規模環境にて）

- adminへの作業負荷集中
- admin権限割当者の増加(本来不要な人に)
- プロジェクト間共用カスタムクエリが積極的に利用されない。（作成/編集作業がユーザで作業完結せず、adminにいちいち頼む必要が有る事は、利用する上での心理的障壁になる）

　結果的に、同一内容カスタムクエリの **各プロジェクト個別作成/編集** が発生し、 **トータルの作業負荷増加、作業ミス増加を招いている。**

　カスタムクエリの指定プロジェクト間共用利用自体は、 カスタムクエリをロールベースでアクセス制御することで可能のため、本稿では触れない。
詳細→  https://redmine.tokyo/issues/250

　いちadminとしては、カスタムクエリの作成時だけならまだしも、設定変更時に自分が毎回設定反映必要な機能などユーザに使わせたくない。

　システムレベルのロール割当がadmin権限のみの現状では、プロジェクト間で共通する設定をadmin権限で実施必要な事は、権限管理のスジ的には間違っていない。
　しかし、結果として、ユーザで作業完結せず、adminに作業負荷が集中する。そのためにプロジェクト間の共用カスタムクエリ機能が積極的に利用されない。生産性を落としており勿体無い。

---

# プロジェクト構成例

　実際の適用例として、下記構成のRedmine環境を想定する。数百人ベースの製造業なら一般的な構成である。

　RM社には、Tokyo事業部があり、製品A,B,C,Dの開発/販売をグローバルに行っている。各業務をRedmineのチケットにて作業管理しており、業務のKPIもチケットから算出している。

## プロジェクト
　Tokyo事業部の下に、製品A,製品B,製品C,Tokyo-管理部のサブプロジェクトを置く。
　製品Aの下には、日本国内/中国/米国/EUなどの地域単位サブプロジェクトを置く（各地域の販売/事故情報等）

<img width="500" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61474/1916a592-2fb8-dc3e-03b1-1ef70ed07a70.png">

## ロール

　製品プロジェクト単位で、販売担当、開発担当、品質保証担当の職種毎に、ロールが定義され担当者が割り当てられている。
　各職種の計数管理担当者には、PJの公開カスタムクエリ作成の権限を割り当てている。（ロール指定）
　各製品プロジェクトには、KPI算出用カスタムクエリが定義されている。（各製品間で異なる）このカスタムクエリは、製品プロジェクトの管理者が作成/編集可能とする。
また、他製品用のカスタムクエリは無関係なので表示しない。

各職種毎の管理指標用カスタムクエリは、自職種のメンバのみ利用可能としている。（各製品間共通）
（販売部門に見せたく無い情報、職種間で相反し兼ねないKPI、、、）

<img width="500" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61474/99bc9f43-5730-1b99-d782-9343fc54013c.png">

<img width="500" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61474/8641f951-06ee-0a50-7e61-6e60732ee177.png">


## カスタムクエリ編集
　販売部門の計数担当者は、各製品の販売担当用カスタムクエリを随時変更する必要がある。（もちろん製品個別設定でなく一括操作可能にしないとミスる。）

**販売部門の計数担当者にadmin権限渡せば可能だが、adminはふつー拒否する。**

結果として、計数担当者は **各プロジェクトでカスタムクエリの個別作成/編集を行わざるを得なくなる。**
これが、これまでのRedmineの現状。

---
# 解決方法
　この問題の解決策として、**admin以外もプロジェクト間共用カスタムクエリを作成/編集可能とすれば良い。（Redmine本体改造）**
　無制限に作成可能とすると、カスタムクエリSPAM/偽カスタムクエリが発生する可能性があるため、admin以外で作成/編集可能なユーザ、クエリは最小限にする必要がある。

　カスタムクエリ利用者のアクセス制御に関しては変更無い。
（従来のロールベースアクセス制限をそのまま利用）

# Redmine自体のソース変更内容

　**操作者＝カスタムクエリ作成者の場合、admin同様に無条件にプロジェクト間共用カスタムクエリを編集可能とする処理を追加した。**
（本来はシステムレベルのロール割当とDB設計変更が必要だが、今回は簡易的な方法として、自分が作成したカスタムクエリの場合に可能とした。）

## Redmine本体のコード変更箇所

実際の修正内容は下記参照(Redmine3.4ベースのパッチ済コード有)
https://github.com/y503unavailable/redmine/issues/28

変更箇所は下記3ファイルのみ（合計4行）

| 変更対象ファイル  |    変更点 |
|:---------------------------|:------------------------|
| app/models/query.rb|操作者＝クエリ作成者の場合、無条件にカスタムクエリを編集可能とする処理を追加した。|
| app/controllers/queries_controller.rb|adminまたはプロジェクト内クエリ以外の場合、強制的に個人単位クエリに再設定している処理を回避した。|
|app/views/queries/_form.html.erb|カスタムクエリ編集画面の表示権限設定部分、adminのみ/クエリ作成時のみ表示している箇所を、クエリ作成者にも表示するように変更した。|

---
# 運用例
Redmine本体に上記変更を実施した上で、下記手順でカスタムクエリの作成/編集を行う。
なお、カスタムクエリ利用者の作業には変更無い。

## 前準備

|作業者|作業内容:|
|:---------------------------|:------------------------|
|admin|各カスタムクエリ表示制御に用いるロールを作成する。|
|プロジェクト-admin|カスタムクエリの作成者に、プロジェクト内のクエリ作成/保存権限を割り当てる。
||カスタムクエリの利用者に、プロジェクト内のクエリ表示用ロールを割り当てる。|

今回は、下記のロールを定義し、プロジェクト内各担当者に割当済とする。

|作業内容|割当ロール:|
|:---------------------------|:------------------------|
|販売部門用カスタムクエリ利用|販売担当|
|販売部門用カスタムクエリ作成/編集|販売_計数管理|

<img width="500" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61474/99bc9f43-5730-1b99-d782-9343fc54013c.png">

## プロジェクト間共有カスタムクエリ作成

クエリ作成者には、プロジェクトのクエリ作成、クエリ保存の権限が必要。

|作業者|作業内容:|
|:---------------------------|:------------------------|
|カスタムクエリ作成者|プロジェクト内でカスタムクエリを作成する。|
||「全プロジェクト向け」をチェックする。|
||「表示」-「次のロールのみ」、クエリ利用許可するロールを選択する。|
||カスタムクエリを保存する。|

<img width="400" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61474/9ee02cc1-5614-acbe-9011-e59a466b2a9b.png">

## プロジェクト間共有カスタムクエリ編集

本操作は、カスタムクエリ作成者またはadminが可能。

|作業者|作業内容:|
|:---------------------------|:------------------------|
|カスタムクエリ作成者|カスタムクエリを編集し保存する。|
||表示権限変更も可能(ロール制御/作成者本人のみ/制限無）|

（プロジェクト間共用のカスタムクエリは、特定のプロジェクトに所属しないため、プロジェクト内のクエリ編集/保存ロールによりアクセス制限できない。代用としてカスタムクエリ作成者のIDを利用している）

## プロジェクト間共有カスタムクエリ利用

各プロジェクトにて、カスタムクエリ表示用のロールを割り当てられたユーザが利用可能である。
（今回の例では「販売担当」のロール）

# 補足

今回のパッチはプロトタイプであり、実際に運用するには下記箇所などの修正が望まれる。

- カスタムクエリ作成者を明示し変更可能とする。
（変更依頼先が判らないため）

- admin以外の全プロジェクト向けカスタムクエリ作成は、ロール指定分のみに制限する。
（誤って全員に公開、無関係なカスタムクエリが溢れたらSPAMでしかない）

- カスタムクエリのフィルタに、PJ指定の対象バージョン/カテゴリ欄を設定できない。設定していると編集時にクリアされる。
　（共有＝「すべてのプロジェクト」を指定したバージョンは利用可能。この制約は今回の改造によるものではない。）

# まとめ

Redmineのソースコードを数行修正するだけで、プロジェクト間共有のカスタムクエリをadmin以外が作成可能になり、大規模環境でカスタムクエリ機能を有効活用できるようになります。

# 最後に

RedmineはOSS(Open Source Software)です。
単なる無料ソフトではありません。

ソースコードは公開され、機能提案/修正をオープンに受け付けています。
便利に利用するだけでなく、機能不足な点は、Redmine本家などに積極的に声を上げて、より使い良い物に育てていきましょう。

本件はRedmine本家にチケット起票済です。
賛成の方は本家に一票ください。(コメント最初に +1 )
Allowing non-admin to create/edit custom queries shared among projects
http://www.redmine.org/issues/31349

（宣伝）このようなRedmineの改造記事を下記に掲載しています。よろしければ参照ください。
https://redmine.tokyo/projects/unofficialcooking/issues