/// <summary>
            /// Gets employee authorized to current store.
            /// </summary>
            /// <param name="request">The data service request.</param>
            /// <returns>The data service response.</returns>
            private SingleEntityDataServiceResponse <Employee> GetAuthorizedEmployee(GetEmployeeAuthorizedOnStoreDataRequest request)
            {
                EmployeeDataManager dataManager = this.GetDataManagerInstance(request.RequestContext);
                Employee            employee    = dataManager.GetAuthorizedEmployeeOnStore(request.RequestContext.GetPrincipal().ChannelId, request.StaffId);

                return(new SingleEntityDataServiceResponse <Employee>(employee));
            }
            /// <summary>
            /// Associates the current employee and terminal in <paramref name="context"/>.
            /// </summary>
            /// <param name="requestContext">The request context.</param>
            /// <remarks>If employee cannot hold multiple sessions on different terminals <see cref="UserAuthorizationException"/> is thrown.</remarks>
            private static void CreateStaffSession(RequestContext requestContext)
            {
                ICommercePrincipal principal = requestContext.GetPrincipal();
                string             staffId   = principal.UserId;

                // when no terminal is present, there is no need to enforce single terminal use
                if (principal.IsTerminalAgnostic)
                {
                    throw new InvalidOperationException("A new session can only be created when channel and terminal are present in the request context.");
                }

                if (string.IsNullOrWhiteSpace(staffId))
                {
                    throw new InvalidOperationException("AuthorizeMultipleTerminalUse can only be performed if user is known. Missing UserId from CommercePrincipal.");
                }

                if (!principal.IsEmployee)
                {
                    throw new InvalidOperationException("AuthorizeMultipleTerminalUse can only be performed if user is employee.");
                }

                GetEmployeeAuthorizedOnStoreDataRequest employeeDataRequest = new GetEmployeeAuthorizedOnStoreDataRequest(staffId);
                Employee employee = requestContext.Execute <SingleEntityDataServiceResponse <Employee> >(employeeDataRequest).Entity;

                // managers are not required to keep track of sessions
                if (employee.Permissions.HasManagerPrivileges)
                {
                    return;
                }

                // helper does most of the hard lifting regarding fallback logic and real time communication
                StaffRealTimeSecurityValidationHelper staffSecurityHelper = StaffRealTimeSecurityValidationHelper.Create(
                    requestContext,
                    SecurityVerificationType.Authorization,
                    staffId,
                    principal.ChannelId,
                    principal.TerminalId,
                    password: string.Empty);

                // executes the common set of steps that performs the session creation flow in either HQ, local DB, or HQ with local DB fallback
                ExecuteWorkWithLocalFallback(
                    staffSecurityHelper.GetSecurityVerificationConfiguration(),
                    staffSecurityHelper,
                    () =>
                {
                    return(CreateEmployeeSessionLocalDatabase(requestContext, employee));
                });

                // we always need to create the session on local DB so we can enforce session is open,
                // so if the configuration is set to use RealTime service, also creates the session on local DB
                if (staffSecurityHelper.GetSecurityVerificationConfiguration() == LogOnConfiguration.RealTimeService)
                {
                    CreateEmployeeSessionLocalDatabase(requestContext, employee);
                }

                RetailLogger.Log.CrtServicesStaffAuthorizationServiceUserSessionStarted(staffId, requestContext.GetTerminal().TerminalId);
            }
            /// <summary>
            /// Authorizes the staff using the local database.
            /// </summary>
            /// <param name="context">The request context.</param>
            /// <param name="staffId">The staff identifier to be verified.</param>
            /// <param name="enforceSessionOpened">A value indicating whether the authorization service will verify and fail if the user does not have a session opened.</param>
            /// <returns>The employee object.</returns>
            private static Employee AuthorizeEmployeeLocalDatabase(RequestContext context, string staffId, bool enforceSessionOpened)
            {
                if (context.GetPrincipal().IsChannelAgnostic)
                {
                    throw new InvalidOperationException("Local authorization can only be performed if principal is not channel agnostic.");
                }

                // Check if user is blocked
                GetEmployeeAuthorizedOnStoreDataRequest employeeDataRequest = new GetEmployeeAuthorizedOnStoreDataRequest(staffId);
                Employee employee = context.Execute <SingleEntityDataServiceResponse <Employee> >(employeeDataRequest).Entity;

                if (employee == null || employee.Permissions == null)
                {
                    throw new UserAuthorizationException(SecurityErrors.Microsoft_Dynamics_Commerce_Runtime_LocalLogonFailed, "User could not be authorized. The user is blocked, not exists, or permission is not found.");
                }

                if (employee.IsBlocked)
                {
                    RetailLogger.Log.CrtServicesStaffAuthorizationServiceBlockedUserAccessAttempt(employee.StaffId);
                    throw new UserAuthorizationException(SecurityErrors.Microsoft_Dynamics_Commerce_Runtime_AuthorizationFailed, "The user is not authorized.");
                }

                bool isRequestWithElevatedPrivileges = context.GetPrincipal().ElevatedOperation != (int)RetailOperation.None;

                // session only needs to be enforces if requested by caller (enforceSessionOpened) and request is bound to a terminal
                // and it is not a manager override
                // also, session requirement does not apply for managers
                if (!employee.Permissions.HasManagerPrivileges && enforceSessionOpened && !context.GetPrincipal().IsTerminalAgnostic&& !isRequestWithElevatedPrivileges)
                {
                    // validates that employee has open session
                    CheckEmployeeHasOpenSessionDataRequest checkEmployeeSessionRequest = new CheckEmployeeHasOpenSessionDataRequest();
                    bool isStaffSessionOpenOnTerminal = context.Execute <SingleEntityDataServiceResponse <bool> >(checkEmployeeSessionRequest).Entity;

                    if (!isStaffSessionOpenOnTerminal)
                    {
                        throw new UserAuthorizationException(SecurityErrors.Microsoft_Dynamics_Commerce_Runtime_UserSessionNotOpened, "User must open a session before executing this request.");
                    }
                }

                return(employee);
            }