以前に管理サービスの禁止方法を記事にしました。管理サービスを禁止すると、色々と不便になりますが、最初に困るのはユーザー管理でしょうか。
Oracle APEXはユーザー管理を行うAPIを提供しているので、それを使うことで管理画面を自作することができます。試しに簡単なアプリを作ってみました。Oracle APEXが提供しているビューとAPIを使うことで比較的容易にアプリケーションは作れました。
とはいえ、管理サービスを禁止するくらいセキュリティについて意識するのであれば、ユーザー管理はOAuth2などの認証プロトコルを使用して、外部の認証サービスを使うようにすべきでしょう。そこまでいかなくても、自前で表を作ってユーザー情報を保存し、カスタム認証を実装しても良いのではないかと思います。
アプリケーション自体は単純な作りですが、ページ・アイテムが多く、それを手作りする必要があるので、最初にアプリケーションのエクスポートを紹介します。
https://github.com/ujnak/apexapps/blob/master/exports/sampleusermgmt.sql
では、作り方の方を紹介します。
最初に空のアプリケーションを作成します。名前はユーザー管理とします。
select APEX_UTIL.GET_USER_ID("USER_NAME") "USER_ID", "WORKSPACE_ID", "WORKSPACE_NAME", "WORKSPACE_DISPLAY_NAME", "FIRST_SCHEMA_PROVISIONED", "USER_NAME", "FIRST_NAME", "LAST_NAME", "EMAIL", "DATE_CREATED", "DATE_LAST_UPDATED", "AVAILABLE_SCHEMAS", "IS_ADMIN", "IS_APPLICATION_DEVELOPER", "ACCOUNT_LOCKED", "DESCRIPTION", "PASSWORD_VERSION", "ACCOUNT_EXPIRY", "FAILED_ACCESS_ATTEMPTS", "PROFILE_IMAGE_NAME", "PROFILE_MIMETYPE", "PROFILE_FILENAME", "PROFILE_CHARSET" from "APEX_WORKSPACE_APEX_USERS"
名前はユーザー一覧、ソースのタイプはSQL問合せです。
次にフォームとなるページを作成します。静的コンテンツを使ってページを作ります。
ページ作成ウィザードを起動し、コンポーネントの空白ページを選びます。
名前をユーザー編集、ページ・モードをモーダル・ダイアログとします。オプションの静的コンテンツ・リージョンとして、リージョン1にユーザー編集を指定します。次に進みます。
ダイアログのページなので、ナビゲーションのプリファレンスとしては、このページとナビゲーション・メニューを関連付けないを選択します。次に進みます。
設定内容を確認して、終了をクリックします。
以上で、ダイアログとなるページが作成されました。作成された静的リージョンにページ・アイテムとボタンを配置します。
作成するページ・アイテムは以下です。
P2_USER_ID (非表示)、P2_WORKSPACE、P2_DEFAULT_SCHEMA、P2_USER_NAME、P2_FIRST_NAME、P2_LAST_NAME、P2_WEB_PASSWORD、P2_EMAIL_ADDRESS、P2_ALLOW_ACCESS_TO_SCHEMAS、P2_GROUPS、P2_DEVELOPER_ROLE、P2_DESCRIPTION、P2_ACCOUNT_EXPIRY、P2_ACCOUNT_LOCKED(切替え)、P2_FAILED_ACCESS_ATTEMPTS、P2_CHANGE_PASSWORD_ON_FIRST_USE(切替え)、P2_FIRST_PASSWORD_USE_OCCURED(切替え)
見やすくなるようにレイアウトを変更しましょう。
次にボタンですが、
B_CREATE、B_SUBMIT、B_DELETE、B_CLOSE
の4つのボタンを作成します。それぞれ、作成、変更の適用、削除と閉じる、というラベルを割り与えます。B_CREATEは主キーであるP2_USER_IDがNULLの場合に表示し、B_SUBMIT、B_DELETEは反対にP2_USER_IDがNULLでない場合に表示するようサーバー側の条件を構成します。標準で、Create、Change、Delete、Closeとして推奨されているボタン位置があります。ただ、Deleteだけは作成と変更の適用から離すために、Closeの場所に配置しました。
次にレポートのページに戻り、ユーザーの新規登録のボタンを作成します。ボタン名をB_CREATEとし、ラベルを新規登録、ボタン位置は対話モード・レポートの検索バーの右に配置します。
動作のアクションはこのアプリケーションのページにリダイレクトを選択し、ターゲットはページ2として、フォームを作成したページを指定します。
選択した行の編集フォームを開くよう、対話モード・レポートのAttributesに含まれるリンクを設定します。リンク列はカスタム・ターゲットへのリンクを選択します。
ターゲットは、ページを2、アイテムの設定として名前をP2_USER_ID、値は#USER_ID#を設定します。キャッシュのクリアも2を設定します。
以上で画面に必要なコンポーネントは配置できました。
ここからが今回の本題です。フォームのページに戻ります。
ユーザー情報をフェッチし、ページ・アイテムに設定するプロセスを登録します。APIとしては、APEX_UTIL.FETCH_USERを呼び出します。ヘッダーの後にプロセスを作成し、以下のコードをソースとして設定します。名前をユーザー情報のフェッチとし、タイプはコードを実行を選びます。
DECLARE l_start_date DATE; l_end_date DATE; l_employee_id NUMBER(15,0); l_person_type VARCHAR2(1); l_groups VARCHAR2(1000); BEGIN APEX_UTIL.FETCH_USER( p_user_id => :P2_USER_ID, p_workspace => :P2_WORKSPACE, p_user_name => :P2_USER_NAME, p_first_name => :P2_FIRST_NAME, p_last_name => :P2_LAST_NAME, p_web_password => :P2_WEB_PASSWORD, p_email_address => :P2_EMAIL_ADDRESS, p_start_date => l_start_date, p_end_date => l_end_date, p_employee_id => l_employee_id, p_allow_access_to_schemas => :P2_ALLOW_ACCESS_TO_SCHEMAS, p_person_type => l_person_type, p_default_schema => :P2_DEFAULT_SCHEMA, p_groups => l_groups, p_developer_role => :P2_DEVELOPER_ROLE, p_description => :P2_DESCRIPTION, p_account_expiry => :P2_ACCOUNT_EXPIRY, p_account_locked => :P2_ACCOUNT_LOCKED, p_failed_access_attempts => :P2_FAILED_ACCESS_ATTEMPTS, p_change_password_on_first_use => :P2_CHANGE_PASSWORD_ON_FIRST_USE, p_first_password_use_occurred => :P2_FIRST_PASSWORD_USE_OCCURED); select listagg(apex_util.get_group_name(column_value),':') into :P2_GROUPS from apex_string.split(l_groups, ':'); END;
左ペインをプロセス・ビューに切り替え、データ操作に関するプロセスを3つ追加します。
最初にユーザーを作成するプロセスを追加します。APEX_UTIL.CREATE_USERを呼び出します。名前をユーザーの作成とし、ボタン押下時はB_CREATEとして、作成ボタンがクリックされたときに実行します。実行するコードは以下になります。
DECLARE l_groups varchar2(1000); BEGIN select listagg(apex_util.get_group_id(column_value),':') into l_groups from apex_string.split(:P2_GROUPS, ':'); APEX_UTIL.CREATE_USER ( p_user_name => :P2_USER_NAME, p_first_name => :P2_FIRST_NAME, p_last_name => :P2_LAST_NAME, p_description => :P2_DESCRIPTION, p_email_address => :P2_EMAIL_ADDRESS, p_web_password => :P2_WEB_PASSWORD, p_group_ids => l_groups, p_developer_privs => :P2_DEVELOPER_ROLE, p_default_schema => :P2_DEFAULT_SCHEMA, p_allow_access_to_schemas => :P2_ALLOW_ACCESS_TO_SCHEMAS, p_change_password_on_first_use => :P2_CHANGE_PASSWORD_ON_FIRST_USE ); END;
ユーザーの更新では、APEX_UTIL.EDIT_USERを呼び出します。ボタンB_SUBMITが押された時に実行します。
declare l_groups varchar2(1000); BEGIN select listagg(apex_util.get_group_id(column_value),':') into l_groups from apex_string.split(:P2_GROUPS, ':'); APEX_UTIL.EDIT_USER ( p_user_id => :P2_USER_ID, p_user_name => :P2_USER_NAME, p_first_name => :P2_FIRST_NAME, p_last_name => :P2_LAST_NAME, p_web_password => :P2_WEB_PASSWORD, p_new_password => :P2_WEB_PASSWORD, p_email_address => :P2_EMAIL_ADDRESS, -- p_start_date => l_start_date, -- p_end_date => l_end_date, -- p_employee_id => l_employee_id, p_allow_access_to_schemas => :P2_ALLOW_ACCESS_TO_SCHEMAS, -- p_person_type => l_person_type, p_default_schema => :P2_DEFAULT_SCHEMA, p_group_ids => l_groups, p_developer_roles => :P2_DEVELOPER_ROLE, p_description => :P2_DESCRIPTION, p_account_expiry => :P2_ACCOUNT_EXPIRY, p_account_locked => :P2_ACCOUNT_LOCKED, p_failed_access_attempts => :P2_FAILED_ACCESS_ATTEMPTS, p_change_password_on_first_use => :P2_CHANGE_PASSWORD_ON_FIRST_USE, p_first_password_use_occurred => :P2_FIRST_PASSWORD_USE_OCCURED); END;
BEGIN APEX_UTIL.REMOVE_USER(p_user_id=> :P2_USER_ID); END;
最後にダイアログを閉じるプロセスを追加します。
レポートのページにダイアログがクローズしたときに、レポートをリフレッシュする動的アクションを定義します。動的アクション・ビューを開き、ダイアログのクローズで動的アクションを作成します。
名前はレポートのリフレッシュとし、タイミングのイベントはダイアログのクローズ、選択タイプはリージョン、リージョンはユーザー一覧とします。
Trueアクションを作成します。アクションはリフレッシュ、影響を受ける要素は、選択タイプがリージョン、リージョンはユーザー一覧になります。
以上でアプリケーションは完成です。
アプリケーションを実行し、ユーザーを登録しようとすると、以下のエラーが発生します。
APIコールは禁止されています。 管理者に連絡してください。
Oracle APEXで作成したアプリケーションからは、管理系のAPIの呼び出しが禁止されています。こちらの制限を解除する必要があります。
アプリケーション定義のセキュリティを開き、データベース・セッションのセクションに含まれる、ランタイムAPIの使用状況のワークスペース・リポジトリを変更にチェックを入れます。
再度、アプリケーションを実行すると、表題にあるGIF動画のような動作になります。
APIの確認が目的なので、アプリケーションとしては改良の余地は多々あります。たとえば、パスワードを隠す、など。また、本アプリを本番環境にインストールするのは全くお勧めしません。あくまでサンプルです。
本記事は以上になります。Oracle APEXのアプリケーション開発の一助になれば幸いです。
完