接下來繼續說明帳號與權限元件所提供的功能,以及呼叫者端(展示層的網頁程式)如何使用這個元件。
下圖是帳號與權限元件關聯圖,
帳號與權限元件 EmployeeAuthorityLogic 主要提供三大類的功能,
- 初始化
- 權限判斷結果
- 資料存取
1. 初始化
1-1. 建構式 EmployeeAuthorityLogic(IAuthenticationConditionProvider)
EmployeeAuthorityLogic 只負責取得帳號在指定作業選項的授權設定值與提供權限判斷結果。帳號名稱與作業選項代碼需要由外部提供,而介面 IAuthenticationConditionProvider 負責提供這類相關的條件值。通常 IAuthenticationConditionProvider 交由各個管理頁共用元件實作。若呼叫者端不需要使用後續「權限判斷結果」的功能,則不需要輸入參數 IAuthenticationConditionProvider。
1-2. 開放外部元件自訂帳號授權結果 SetCustomEmployeeAuthorizationResult(ICustomEmployeeAuthorizationResult)
EmployeeAuthorityLogic 透過介面 ICustomEmployeeAuthorizationResult 取得作業選項子項目的擁有者資訊做為權限判斷條件,或者是取回外部元件自訂的權限判斷結果取代原本的結果值。
此外,系統預設會在建構式時檢查 IAuthenticationConditionProvider 的物件是否也有實作介面 ICustomEmployeeAuthorizationResult,若有就自動設定。通常各個管理頁共用元件會實作此介面。
1-3. 初始化授權結果
依照前述初始化功能得到的條件(帳號、作業選項代碼、是否有自訂帳號授權結果)取得並且暫存相關的授權設定值在 EmployeeAuthorizations 物件裡。
InitialAuthorizationResultOfTopPage() 提供給「作業選項」的最上層使用(例如:帳號清單頁)。
InitialAuthorizationResultOfSubPages() 提供給「作業選項的子項目」使用(例如:帳號設定頁)。
2. 權限判斷結果
使用「1-3. 初始化授權結果」暫存的授權設定值,依據權限規則回傳各項權限判斷結果。
- CanOpenThisPage()
檢查是否可開啟此頁面,清單頁載入時使用。
- CanEditThisPage(bool useTopRule, string ownerAccount, int ownerDeptId)
檢查是否可編輯此頁面,設定頁載入時使用,或者是清單頁用來判斷(子項目)清單中各項資料的編輯鈕是否該出現。
- CanDelThisPage(string ownerAccount, int ownerDeptId)
檢查是否可刪除此頁面,清單頁用來判斷(子項目)清單中各項資料的刪除鈕是否該出現。
- CanAddSubItemInThisPage()
檢查是否可在此頁面新增子項目,(新增資料模式的)設定頁載入時使用。
3. 資料存取
3-1. 讀取暫存的授權設定值
- CanReadSubItemOfOthers(), CanReadSubItemOfCrew(), CanReadSubItemOfSelf()
可否閱讀(任何人的、同部門的、自己的)子項目。
- CanEditSubItemOfOthers(), CanEditSubItemOfCrew(), CanEditSubItemOfSelf()
可否修改(任何人的、同部門的、自己的)子項目。
3-2. 存取資料庫
- GetYYYList()
- GetYYYData()
- InsertYYYData()
- UpdateYYYData()
- DeleteYYYData()
取得資料用的方法名稱皆以 Get 開頭命名,而不管是取得清單資料或是單一資料,皆使用 DataSet 存放回傳值,留給 Stored Procedure 可回傳多個資料表的彈性。
新增資料、更新資料、刪除資料用的方法名稱以順序以 Insert, Update, Delete 開頭命名。
若執行上述存取資料庫用的方法失敗了,可使用 GetDbErrMsg() 取得資料層回傳的錯誤訊息文字。
接下來以「帳號管理」的帳號清單頁、帳號設定頁為例說明網頁程式使用帳號與權限元件的方式。
帳號清單頁 Account-List.aspx.cs
初始化元件:
public partial class Account_List : BasePage { protected AccountCommonOfBackend c; protected EmployeeAuthorityLogic empAuth; // ...略... protected void Page_PreInit(object sender, EventArgs e) { c = new AccountCommonOfBackend(this.Context, this.ViewState); // ...略... empAuth = new EmployeeAuthorityLogic(c); empAuth.InitialAuthorizationResultOfTopPage(); // ...略... }
Line 9: 產生「帳號管理」專屬的管理頁共用元件。
Line 12: 產生帳號與權限元件,同時將管理頁共用元件傳入提供驗證時需要的條件值。
Line 13: 初始化授權結果,取得並且暫存目前登入帳號被授權使用「帳號管理」的授權設定值。
開啟頁面時,判斷是否允許開啟此頁面:
protected void Page_Load(object sender, EventArgs e) { // ...略... if (!IsPostBack) { if (!empAuth.CanOpenThisPage()) { Response.Redirect(c.BACK_END_HOME); } // ...略... } // ...略... }
Line 7, 9: 詢問帳號與權限元件目前登入帳號是否可開啟此頁面,如果不允許則跳轉至後台首頁,不讓登入帳號的使用者看到任何相關內容。
使用者介面元素控制:
private void LoadUIData() { //...略... //HUD if (empAuth.CanAddSubItemInThisPage()) { hud.SetButtonVisible(HudButtonNameEnum.AddNew, true); hud.SetButtonAttribute(HudButtonNameEnum.AddNew, HudButtonAttributeEnum.JsInNavigateUrl, string.Format("popWin('Account-Config.aspx?act={0}', 700, 600);", ConfigFormAction.add)); } //...略... } //...略... protected void rptAccounts_ItemDataBound(object sender, RepeaterItemEventArgs e) { //...略... HtmlAnchor btnEdit = (HtmlAnchor)e.Item.FindControl("btnEdit"); //...略... LinkButton btnDelete = (LinkButton)e.Item.FindControl("btnDelete"); //...略... string ownerAccount = drvTemp.ToSafeStr("OwnerAccount"); int ownerDeptId = Convert.ToInt32(drvTemp["OwnerDeptId"]); btnEdit.Visible = (empAuth.CanEditThisPage(false, ownerAccount, ownerDeptId) || c.IsMyAccount(empAccount)); if (!empAuth.CanDelThisPage(ownerAccount, ownerDeptId) || empAccount == "admin" || empAccount == c.GetEmpAccount()) { btnDelete.Visible = false; } }
Line 6~11: 詢問帳號與權限元件目前登入帳號是否可在此頁面新增子項目,如果可以則在畫面上顯示新增帳號的按鈕(系統預設隱藏此按鈕)。
從 Line 18 開始,是繪製清單項目的程式碼。
Line 28, 29: 取得輪詢到的帳號資料的擁有者資訊(擁有者帳號 OwnerAccount、擁有者所屬部門代碼 OwnerDeptId)。
Line 31: 詢問帳號與權限元件目前登入帳號是否可編輯這項帳號資料,若不行則隱藏修改鈕(如上圖所示,右側綠底的按鈕)。
使用帳號與權限元件的方法
CanEditThisPage(bool useTopRule, string ownerAccount, int ownerDeptId)
第一個參數 useTopRule 使用 false,代表使用權限規則中「作業選項的子項目」的設定值。
另外需傳入 Line 28, 29 取得的擁有者資訊,權限判斷才會正確。
Line 33~38: 詢問帳號與權限元件目前登入帳號是否可刪除這項帳號資料,若不行則隱藏刪除鈕(如上圖所示,右側紅底的按鈕)。
使用帳號與權限元件的方法
CanDelThisPage(string ownerAccount, int ownerDeptId)
這個方法只會使用權限規則中「作業選項的子項目」的設定值,因此不像 CanEditThisPage() 需要 useTopRule 參數。
* 完整程式碼請參考 Account-List.aspx.cs
帳號設定頁 Account-Config.aspx.cs
初始化元件:
public partial class Account_Config : System.Web.UI.Page { protected AccountCommonOfBackend c; protected EmployeeAuthorityLogic empAuth; // ...略... protected void Page_PreInit(object sender, EventArgs e) { c = new AccountCommonOfBackend(this.Context, this.ViewState); // ...略... empAuth = new EmployeeAuthorityLogic(c); empAuth.InitialAuthorizationResultOfSubPages(); }
Line 10: 產生「帳號管理」專屬的管理頁共用元件。
Line 13: 產生帳號與權限元件,同時將管理頁共用元件傳入提供驗證時需要的條件值。
Line 14: 初始化授權結果,取得並且暫存目前登入帳號被授權使用「帳號管理」的授權設定值,與清單頁不同的是這裡使用 InitialAuthorizationResultOfSubPages() 方法名稱結尾為 SubPages,不是清單頁用的 TopPage。
開啟頁面時,判斷是否允許開啟此頁面:
protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { // Authenticate if (c.qsAct == ConfigFormAction.edit && !(empAuth.CanEditThisPage() || c.IsMyAccount()) || c.qsAct == ConfigFormAction.add && !empAuth.CanAddSubItemInThisPage()) { string jsClose = "closeThisForm();"; ClientScript.RegisterStartupScript(this.GetType(), "invalid", jsClose, true); return; } // ...略... } // ...略... }
Line 6~12: 詢問帳號與權限元件目前登入帳號是否可開啟此頁面(依 c.qsAct 區分是新增或是編輯模式),如果不允許則關閉目前網頁(因為設定頁皆開啟於獨立的網頁視窗),並且停止載入本設定頁的所有資料,不讓登入帳號的使用者看到任何相關內容。
* Line 6 使用的方法 CanEditThisPage() 之所以不用傳入擁有者資訊是因為管理頁共用元件實作了介面 ICustomEmployeeAuthorizationResult,透過實作的介面方法 InitialAuthorizationResult(bool isTopPageOfOperation, EmployeeAuthorizations authorizations) 將擁有者資訊交給了帳號與權限元件。這部分屬於客製化權限判斷,將另文說明。
* 完整程式碼請參考 Account-Config.aspx.cs
沒有留言:
張貼留言