2018/04/24

SampleCMS 帳號與權限系統元件說明:客製化權限判斷

接續上一篇 元件提供的功能與使用方式 結尾提到的,(帳號設定頁)"使用的方法 CanEditThisPage() 之所以不用傳入擁有者資訊是因為管理頁共用元件實作了介面 ICustomEmployeeAuthorizationResult,透過實作的介面方法 InitialAuthorizationResult(bool isTopPageOfOperation, EmployeeAuthorizations authorizations) 將擁有者資訊交給了帳號與權限元件",本篇繼續說明介面 ICustomEmployeeAuthorizationResult 的作用以及需負責的工作。

帳號與權限元件透過介面 ICustomEmployeeAuthorizationResult 開放給外部元件自訂帳號授權結果,透過這個介面取得作業選項子項目的擁有者資訊做為權限判斷條件,或者是取回外部元件自訂的權限判斷結果取代原本的結果值。

下列為帳號與權限元件初始化授權結果的程式碼,
        /// <summary>
        /// 初始化最上層頁面授權結果
        /// </summary>
        public void InitialAuthorizationResultOfTopPage()
        {
            InitialAuthorizationResult(true);
        }

        /// <summary>
        /// 初始化下層頁面授權結果
        /// </summary>
        public void InitialAuthorizationResultOfSubPages()
        {
            InitialAuthorizationResult(false);
        }

        /// <summary>
        /// 初始化授權結果
        /// </summary>
        protected virtual void InitialAuthorizationResult(bool isTopPageOfOperation)
        {
            this.isTopPageOfOperation = isTopPageOfOperation;

            //取得指定作業代碼的後端身分可使用權限
            IDataAccessCommand cmd = DataAccessCommandFactory.GetDataAccessCommand(DBs.MainDB);
            spEmployeeRoleOperationsDesc_GetDataOfOp cmdInfo = new spEmployeeRoleOperationsDesc_GetDataOfOp()
            {
                OpId = opIdOfPage,
                RoleName = roleName
            };

            DataSet dsRoleOp = cmd.ExecuteDataset(cmdInfo);

            //從資料集載入身分的授權設定
            LoadRoleAuthorizationsFrom(dsRoleOp);

            if (custEmpAuthResult != null)
            {
                //自訂帳號授權結果
                EmployeeAuthorizationsWithOwnerInfoOfDataExamined authAndOwner = custEmpAuthResult.InitialAuthorizationResult(isTopPageOfOperation, authorizations);
                ownerAccountOfDataExamined = authAndOwner.OwnerAccountOfDataExamined;
                ownerDeptIdOfDataExamined = authAndOwner.OwnerDeptIdOfDataExamined;
                this.authorizations = authAndOwner;

                if (authAndOwner.IsTopPageOfOperationChanged)
                {
                    this.isTopPageOfOperation = authAndOwner.IsTopPageOfOperation;
                }

                return;
            }
        }

Line 1~15: InitialAuthorizationResultOfTopPage() 與 InitialAuthorizationResultOfSubPages() 的差別只在 this.isTopPageOfOperation 是 true 或 false。

Line 24~35: 依照目前的作業選項代碼 opId 和登入者的身分 roleName 從資料庫取得授權設定並且暫存。

Line 37~51: 本篇重點,客製化權限判斷。

Line 40: 將暫存的授權設定提供給外部元件,取回自訂帳號授權結果。

Line 41, 42: 暫存外部元件提供的擁有者資訊。

Line 43: 使用外部元件提供的授權設定,取代暫存的授權設定。
(類別 EmployeeAuthorizationsWithOwnerInfoOfDataExamined 繼承自 EmployeeAuthorizations)

Line 45~48: 如果外部元件有更改 isTopPageOfOperation 值,改用外部元件指定的值。
(例如:帳號與權限元件原本被指定以「作業選項」的授權值做權限判斷,但是外部元件認為要改用「作業選項的子項目」的授權值做權限判斷)

上述 Line 41, 42 取得的擁有者資訊,會被用在 CanEditThisPage() ,以下為 CanEditThisPage() 的程式碼,
        /// <summary>
        /// 檢查是否可編輯此頁面
        /// </summary>
        public virtual bool CanEditThisPage()
        {
            return CanEditThisPage(isTopPageOfOperation, ownerAccountOfDataExamined, ownerDeptIdOfDataExamined);
        }

        /// <summary>
        /// 檢查是否可編輯此頁面
        /// </summary>
        public virtual bool CanEditThisPage(bool useTopRule, string ownerAccount, int ownerDeptId)
        {
            bool result = false;

            if (useTopRule)
            {
                result = authorizations.CanEdit;
            }
            else
            {
                if (authorizations.CanEditSubItemOfOthers)
                {
                    result = true;
                }
                else if (authorizations.CanEditSubItemOfCrew
                    && deptId > 0
                    && deptId == ownerDeptId)
                {
                    result = true;
                }
                else if (authorizations.CanEditSubItemOfSelf
                    && empAccount != ""
                    && empAccount == ownerAccount)
                {
                    result = true;
                }
            }

            return result;
        }

Line 6: 使用暫存的擁有者資訊做為條件做權限判斷。

以上為介面 ICustomEmployeeAuthorizationResult 在帳號與權限元件之中的作用。


接著說明實作介面 ICustomEmployeeAuthorizationResult 的外部元件需負責的工作,
以「帳號管理」專屬的管理頁共用元件 AccountCommonOfBackend 為例,下列為實作介面的程式碼,
    [Description("後台帳號管理頁的共用元件")]
    public class AccountCommonOfBackend : BackendPageCommon, ICustomEmployeeAuthorizationResult
    {
        // ...略...

        #region ICustomEmployeeAuthorizationResult

        public EmployeeAuthorizationsWithOwnerInfoOfDataExamined InitialAuthorizationResult(bool isTopPageOfOperation, EmployeeAuthorizations authorizations)
        {
            EmployeeAuthorizationsWithOwnerInfoOfDataExamined authAndOwner = new EmployeeAuthorizationsWithOwnerInfoOfDataExamined(authorizations);

            if (!isTopPageOfOperation)
            {
                // get owner info for config-form
                IDataAccessCommand cmd = DataAccessCommandFactory.GetDataAccessCommand(DBs.MainDB);
                spEmployee_GetAccountOfId cmdInfo = new spEmployee_GetAccountOfId()
                {
                    EmpId = qsEmpId
                };

                string errCode = "-1";
                string empAccount = cmd.ExecuteScalar<string>(cmdInfo, errCode);
                string dbErrMsg = cmd.GetErrMsg();

                DataSet ds = null;
                if (empAccount != errCode)
                {
                    accountOfData = empAccount;
                    spEmployee_GetData cmdInfoGetData = new spEmployee_GetData()
                    {
                        EmpAccount = empAccount
                    };

                    ds = cmd.ExecuteDataset(cmdInfoGetData);
                    dbErrMsg = cmd.GetErrMsg();

                    if (ds != null && ds.Tables[0].Rows.Count > 0)
                    {
                        DataRow drFirst = ds.Tables[0].Rows[0];

                        authAndOwner.OwnerAccountOfDataExamined = drFirst.ToSafeStr("OwnerAccount");
                        authAndOwner.OwnerDeptIdOfDataExamined = Convert.ToInt32(drFirst["OwnerDeptId"]);
                    }
                }
            }

            return authAndOwner;
        }

        #endregion
    }

Line 10: 預設要回傳的授權結果 EmployeeAuthorizationsWithOwnerInfoOfDataExamined 物件,預設值同傳入的 EmployeeAuthorizations 物件。

Line 12: 若使用的是「作業選項的子項目」的規則,才需要去資料庫取得擁有者資訊。

Line 15~23: 使用網址參數 EmpId 到資料庫取得對應的帳號 EmpAccount。

Line 28: 暫存取回的 EmpAccount,預留給其他功能。

Line 29~43: 使用 EmpAccount 到資料庫取得帳號的擁有者資訊,並且放入要回傳的結果物件裡。

Line 47: 回傳結果。

總結外部元件需負責的工作有兩項,
  1. 回傳的授權結果 EmployeeAuthorizationsWithOwnerInfoOfDataExamined 物件不管外部元件有無更改授權設定值,一定要有回傳值。若沒有更改授權設定值,要從傳入的 EmployeeAuthorizations 物件複製相同的值再回傳。
  2. 負責取得展示層網頁程式指定的「作業選項的子項目」資料擁有者資訊。




沒有留言:

張貼留言