private ServiceResult OnApproveLock(
            ISystemContext context,
            MethodState method,
            NodeId objectId,
            IList <object> inputArguments,
            IList <object> outputArguments)
        {
            DsatsDemo.LockConditionState node = (DsatsDemo.LockConditionState)FindPredefinedNode(objectId, typeof(DsatsDemo.LockConditionState));

            if (!node.EnabledState.Id.Value)
            {
                return(StatusCodes.BadConditionDisabled);
            }

            if (node.LockState.CurrentState.Id.Value != new NodeId(DsatsDemo.Objects.LockStateMachineType_WaitingForApproval, NamespaceIndex))
            {
                return(StatusCodes.BadConditionNotShelved);
            }

            // only admins can approve locks.
            if (!CheckAdminAccess(context))
            {
                return(StatusCodes.BadUserAccessDenied);
            }

            // grant the lock.
            GrantLockToSession(context, node.SessionId.Value, objectId);

            node.SetLock(context);
            node.ReportEvent(context, node);
            node.ClearChangeMasks(context, true);

            return(ServiceResult.Good);
        }
        void LoadDataSourceLocks(ISystemContext context, DsatsDemo.DataSource.DataSource datasource)
        {
            if (datasource == null || datasource.Lock == null)
            {
                return;
            }

            foreach (DsatsDemo.DataSource.LockType source in datasource.Lock)
            {
                DsatsDemo.LockConditionState node = datasource.ReadLock(context, source);

                node.Request.OnCallMethod2          = OnRequestLock;
                node.Release.OnCallMethod2          = OnReleaseLock;
                node.Approve.OnCallMethod2          = OnApproveLock;
                node.LockStateAsString.OnWriteValue = OnChangeLockByWrite;

                if (source.Permission != null)
                {
                    foreach (DsatsDemo.DataSource.CertificatePermissionType permission in source.Permission)
                    {
                        node.SetPermission(permission.Thumbprint);
                    }
                }

                node.AddNotifier(context, Opc.Ua.ReferenceTypeIds.HasEventSource, true, m_rig.Locks);
                m_rig.Locks.AddNotifier(context, Opc.Ua.ReferenceTypeIds.HasEventSource, false, node);

                AddPredefinedNode(context, node);
            }
        }
        /// <summary>
        /// Called when a session is closed.
        /// </summary>
        public override void SessionClosing(OperationContext context, NodeId sessionId, bool deleteSubscriptions)
        {
            lock (Lock)
            {
                List <NodeId> locks = null;

                if (!m_sessionLocks.TryGetValue(sessionId, out locks))
                {
                    return;
                }

                m_sessionLocks.Remove(sessionId);

                for (int ii = 0; ii < locks.Count; ii++)
                {
                    DsatsDemo.LockConditionState node = (DsatsDemo.LockConditionState)FindPredefinedNode(locks[ii], typeof(DsatsDemo.LockConditionState));

                    if (node != null)
                    {
                        node.SessionId.Value    = null;
                        node.ClientUserId.Value = null;
                        node.SubjectName.Value  = null;
                        node.Unlock(SystemContext);
                        node.ReportEvent(SystemContext, node);
                    }
                }
            }
        }
        private ServiceResult OnRequestLock(
            ISystemContext context,
            MethodState method,
            NodeId objectId,
            IList <object> inputArguments,
            IList <object> outputArguments)
        {
            DsatsDemo.LockConditionState node = (DsatsDemo.LockConditionState)FindPredefinedNode(objectId, typeof(DsatsDemo.LockConditionState));

            if (!node.EnabledState.Id.Value)
            {
                return(StatusCodes.BadConditionDisabled);
            }

            if (node.LockState.CurrentState.Id.Value != new NodeId(DsatsDemo.Objects.LockStateMachineType_Unlocked, NamespaceIndex))
            {
                return(StatusCodes.BadConditionAlreadyShelved);
            }

            node.SessionId.Value    = context.SessionId;
            node.ClientUserId.Value = null;
            node.SubjectName.Value  = null;

            // get the current user name.
            if (context.UserIdentity != null)
            {
                node.ClientUserId.Value = context.UserIdentity.DisplayName;
            }

            X509Certificate2 certificate = null;

            // get the client certificate subject name.
            ServerSystemContext systemContext = context as ServerSystemContext;

            if (systemContext != null && systemContext.OperationContext != null && systemContext.OperationContext.Session != null && systemContext.OperationContext.Session.ClientCertificate != null)
            {
                certificate            = systemContext.OperationContext.Session.ClientCertificate;
                node.SubjectName.Value = certificate.Subject;
            }

            node.RequestLock(context);

            // admins get locks immediately.
            if (CheckAdminAccess(context) || (certificate != null && node.HasPermission(certificate)))
            {
                GrantLockToSession(context, node.SessionId.Value, objectId);
                node.SetLock(context);
            }

            node.ReportEvent(context, node);
            node.ClearChangeMasks(context, true);

            return(ServiceResult.Good);
        }
        public ServiceResult OnChangeLockByWrite(
            ISystemContext context,
            NodeState node,
            NumericRange indexRange,
            QualifiedName dataEncoding,
            ref object value,
            ref StatusCode statusCode,
            ref DateTime timestamp)
        {
            DsatsDemo.LockConditionState condition = null;

            BaseInstanceState instance = node as BaseInstanceState;

            if (instance.Parent != null)
            {
                condition = instance.Parent as DsatsDemo.LockConditionState;
            }

            if (condition == null)
            {
                return(StatusCodes.BadNotWritable);
            }

            string lockState = value as string;

            if (lockState == null)
            {
                return(StatusCodes.BadTypeMismatch);
            }

            if (lockState == "Locked")
            {
                ServiceResult result = OnRequestLock(context, condition.Request, condition.NodeId, new object[0], new object[0]);
                value = condition.LockStateAsString.Value;
                return(result);
            }

            else if (lockState == "Unlocked")
            {
                ServiceResult result = OnReleaseLock(context, condition.Request, condition.NodeId, new object[0], new object[0]);
                value = condition.LockStateAsString.Value;
                return(result);
            }

            return(StatusCodes.BadTypeMismatch);
        }
        private ServiceResult OnReleaseLock(
            ISystemContext context,
            MethodState method,
            NodeId objectId,
            IList <object> inputArguments,
            IList <object> outputArguments)
        {
            DsatsDemo.LockConditionState node = (DsatsDemo.LockConditionState)FindPredefinedNode(objectId, typeof(DsatsDemo.LockConditionState));

            if (!node.EnabledState.Id.Value)
            {
                return(StatusCodes.BadConditionDisabled);
            }

            if (node.LockState.CurrentState.Id.Value == new NodeId(DsatsDemo.Objects.LockStateMachineType_Unlocked, NamespaceIndex))
            {
                return(StatusCodes.BadConditionNotShelved);
            }

            // non-admins can only release their own locks.
            if (!CheckAdminAccess(context))
            {
                if (!SessionHasLock(context, objectId))
                {
                    return(StatusCodes.BadUserAccessDenied);
                }
            }

            // revoke the lock.
            RevokeLockForSession(context, node.SessionId.Value, objectId);

            node.SessionId.Value    = null;
            node.ClientUserId.Value = null;
            node.SubjectName.Value  = null;
            node.Unlock(context);
            node.ReportEvent(context, node);
            node.ClearChangeMasks(context, true);

            return(ServiceResult.Good);
        }