text: # Copyright 2019 Contributors to Hyperledger Sawtooth
  #
  # Licensed under the Apache License, Version 2.0 (the "License");
  # you may not use this file except in compliance with the License.
  # You may obtain a copy of the License at
  #
  #     http://www.apache.org/licenses/LICENSE-2.0
  #
  # Unless required by applicable law or agreed to in writing, software
  # distributed under the License is distributed on an "AS IS" BASIS,
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  # See the License for the specific language governing permissions and
  # limitations under the License.
  # -----------------------------------------------------------------------------
  """A base for all proposal message types"""
  
  from rbac.common import addresser
  from rbac.common.base.base_message import BaseMessage
  from rbac.common.logs import get_default_logger
  
  LOGGER = get_default_logger(__name__)
  
  
  class ProposalMessage(BaseMessage):
      """A base for all proposal message types"""
  
      @property
      def address_type(self):
          """The address type from AddressSpace implemented by this class"""
          return addresser.AddressSpace.PROPOSALS
  
      @property
      def object_type(self):
          """The object type from AddressSpace implemented by this class"""
          return addresser.ObjectType.PROPOSAL
  
      @property
      def related_type(self):
          """The related type from AddressSpace implemented by this class"""
          return addresser.ObjectType.NONE
  
      @property
      def relationship_type(self):
          """The related type from AddressSpace implemented by this class"""
          return addresser.RelationshipType.ATTRIBUTES
  
      @property
      def _state_container_prefix(self):
          """Proposal state container name is plural (ProposalsContainer)"""
          return self._name_camel_plural
  
      def validate_state(self, context, message, payload, input_state, store):
          """Validates that:
          1. the proposed user is a User that exists in state (if proposal involves a user)
          2. the proposed role is a Role that exists in state (if a role proposal)
          3. the proposed task is a Task that exists in state (if a task proposal)
          """
          super().validate_state(
              context=context,
              message=message,
              payload=payload,
              input_state=input_state,
              store=store,
          )
          if hasattr(message, "next_id") and not addresser.user.exists_in_state_inputs(
              inputs=payload.inputs,
              input_state=input_state,
              object_id=getattr(message, "next_id"),
              skip_if_not_in_inputs=True,
          ):
              raise ValueError(
                  "User with id {} does not exist in state".format(
                      getattr(message, "next_id")
                  )
              )
          if hasattr(message, "role_id") and not addresser.role.exists_in_state_inputs(
              inputs=payload.inputs,
              input_state=input_state,
              object_id=getattr(message, "role_id"),
              skip_if_not_in_inputs=True,
          ):
              raise ValueError(
                  "Role with id {} does not exist in state".format(
                      getattr(message, "role_id")
                  )
              )
          if hasattr(message, "task_id") and not addresser.task.exists_in_state_inputs(
              inputs=payload.inputs,
              input_state=input_state,
              object_id=getattr(message, "task_id"),
              skip_if_not_in_inputs=True,
          ):
              raise ValueError(
                  "Task with id {} does not exist in state".format(
                      getattr(message, "task_id")
                  )
              )
  