アクセス制御の実装サンプルとして、こちらのアプリケーションを作ってみました。
- 初期アプリケーションの作成(この記事)
- データ・ローディングの実装
- ファセット検索ページの追加
- 対話モード・レポートとフォームの追加
- 対話グリッドの追加
- 認可スキームについて
- ロールが管理者であれば、すべてのタスクを参照することができる。
- ロールがコントリビュータであれば、自分が所属している部署に関するタスクの作成、更新、削除ができる。
- ロールのない従業員は、自分が所属している部署のタスクの参照と自分がアサインされているタスクの更新ができる(タスクの作成と削除は不可)。
クイックSQLによる表の作成
employees
employee_id num /pk
employee_name vc255 /nn
group_name vc255 /nn
projects
project_id num /pk
project_name vc255 /nn
tasks
task_id num /pk
project_id num /references projects
task_name vc255 /nn
assigned_to num /references employees
status vc8 /check OPEN,CLOSED,PENDING,ON-HOLD
start_date
end_date
cost num
budget num
DDLを生成する設定として、以下を指定します。
- オブジェクト接頭辞: PAC
- 主キー: ID列
- 日付データ型: TIMESTAMP WITH LOCAL TIME ZONE
- セマンティクス: デフォルト
- 自動主キー: OFF
- 互換性: 18c以上
- 主キーに表名を接頭辞として付けます: OFF
アプリケーションの作成
begin
insert into pac_employees(employee_name, group_name) values('山田太郎','経理部');
insert into pac_employees(employee_name, group_name) values('岡本一','開発部');
insert into pac_employees(employee_name, group_name) values('北本三郎','営業部');
insert into pac_employees(employee_name, group_name) values('田中節子','営業部');
insert into pac_employees(employee_name, group_name) values('大谷一朗','開発部');
insert into pac_employees(employee_name, group_name) values('虎尾十兵衛','開発部');
insert into pac_employees(employee_name, group_name) values('木下愛','経理部');
insert into pac_employees(employee_name, group_name) values('三浦康太','経理部');
insert into pac_employees(employee_name, group_name) values('森花子','開発部');
insert into pac_employees(employee_name, group_name) values('伊藤和子','営業部');
insert into pac_employees(employee_name, group_name) values('高橋実','経理部');
insert into pac_employees(employee_name, group_name) values('川口けいこ','営業部');
commit;
end;
投入されたデータは以下のSQLで確認できます。
declare
C_APP_ID constant number := <アプリケーションID>;
begin
apex_acl.add_user_role(c_app_id, '虎尾十兵衛', 'ADMINISTRATOR');
apex_acl.add_user_role(c_app_id, '木下愛', 'ADMINISTRATOR');
apex_acl.add_user_role(c_app_id, '三浦康太', 'CONTRIBUTOR');
apex_acl.add_user_role(c_app_id, '森花子', 'CONTRIBUTOR');
apex_acl.add_user_role(c_app_id, '伊藤和子', 'ADMINISTRATOR');
apex_acl.add_user_role(c_app_id, '川口けいこ', 'CONTRIBUTOR');
end;
ADMINISTRATORが管理者、CONTRIBUTORがコントリビュータのロールです。
この作業は作成したアプリケーションに組み込まれたアクセス制御の画面から行うこともできますし、共有コンポーネントのアプリケーション・アクセス制御からも操作することが可能です。
共有コンポーネントからの操作は、以下の画面から行います。
認証スキームの変更
登録された従業員がアプリケーションのユーザーとなるよう、認証スキームを変更します。カスタム認証を作成します。認証に使用するPL/SQLコードは以下になります。従業員の存在だけを確認し、パスワードは無視しています。あくまでもサンプルですので、そのまま使わないよう、お願いします。
function existing_employee (
p_username in varchar2,
p_password in varchar2 )
return boolean
is
l_exists number;
begin
select 1 into l_exists
from pac_employees
where employee_name = p_username;
return true;
exception
when no_data_found then
return false;
end;
PL/SQLコードに登録した認証ファンクションexisting_employeeは、認証ファンクション名として設定し、認証スキームの作成を実行します。
これで認証スキームは作成したものに切り替わります。すでにサインイン済みのセッションは、一旦サインアウトする必要があります。
日本語の従業員名をユーザー名として指定するのは大変なので、ユーザー名を選択リストで選べるようにします。SQLによる動的なLOVを作成します。共有コンポーネントからLOVを開き、タイプがDynamicであるLOV、名前をPAC_EMPLOYEES.EMPLOYEE_NAME_SIGNINとして作成します。
LOVに使用するコードとしては以下を指定します。
select
e.employee_name || ' - ' || e.group_name || ' - ' || r.roles display_name,
e.employee_name return_value
from pac_employees e
left outer join
(
select user_name, listagg(role_name, ',') within group (order by role_name desc) roles
from apex_appl_acl_user_roles
where workspace_id = :WORKSPACE_ID
and application_id = :APP_ID
group by user_name
) r on e.employee_name = r.user_name
order by e.group_name, r.roles desc nulls last
従業員が所属している部署と割り当たっているロールを、一行で表示します。
作成したLOVをログイン・ページに組み込みます。ログイン・ページをページ・デザイナで開き、タイプを選択リスト、テンプレートをOptional Floating、LOVのタイプとして共有コンポーネント、LOVは先ほど作成したPAC_EMPLOYEES.EMPLOYEE_NAME_SIGNIN、追加値の表示はOFF、NULL表示値を- 従業員を選択 -とします。
保存を行い、アプリケーションを実行します。
ログイン画面が変更されています。
選択リストから従業員を選びます。
従業員を選んでサインインします。
管理者ロールを持ったユーザーでサインインすると、管理メニューにアクセスできます。
この機能はアプリケーション作成時にチェックしていると、標準機能として組み込まれます。
アプリケーション・アイテムとアプリケーションの計算の登録
- G_GROUP_NAME = サインインしたユーザーが所属している部門名
- G_IS_ADMINISTRATOR = 管理者ロールを持っているとY、そうでない場合はN
- G_IS_CONTRIBUTOR = コントリビュータ・ロールを持っているとY、そうでない場合はN
select group_name from pac_employees where employee_name = :APP_USER
サインインしたユーザー名より、その所属部門を検索しています。
同様にして、G_IS_ADMINISTRATOR、G_IS_CONTRIBUTORも登録します。
G_IS_ADMINISTRATORは計算タイプとして、ファンクション本体を選びます。計算には以下のPL/SQLコードを指定します。
if apex_acl.has_user_role( p_role_static_id => 'ADMINISTRATOR' ) then return 'Y'; end if; return 'N';
サインインしているユーザーが管理者ロールを持っているときに、Y、そうでないときにNが設定されるように、APEX_ACL.HAS_USER_ROLEファンクションを呼び出しています。
G_IS_CONTRIBUTORも同様ですが、p_role_static_idはCONTRIBUTORになります。
if apex_acl.has_user_role( p_role_static_id => 'CONTRIBUTOR' ) then return 'Y'; end if; return 'N';
準備作業となるアプリケーションの作成は以上で完了です。
アプリケーションを実行し(すでにサインインしているセッションがあれば、一旦サインアウトし)、サインインを実施してみましょう。
設定内容を確認するため、開発者ツール・バーよりセッションを実行します。ビューにアプリケーション・アイテムを選択し、設定をクリックすると、今までに登録したアプリケーション・アイテムG_GROUP_NAME、G_IS_ADMINISTRATOR、G_IS_CONTRIBUTORに値が設定されていることが確認できるはずです。
次は、データ・ローディングを実装して、CSVファイルを表に取り込みます。