示例#1
0
    def createResource(self,
                       resource: Resource,
                       parentResource: Resource = None,
                       originator: str = None) -> Result:
        Logging.logDebug(
            f'Adding resource ri: {resource.ri}, type: {resource.ty:d}')

        if parentResource is not None:
            Logging.logDebug(f'Parent ri: {parentResource.ri}')
            if not parentResource.canHaveChild(resource):
                if resource.ty == T.SUB:
                    err = 'Parent resource is not subscribable'
                    Logging.logWarn(err)
                    return Result(rsc=RC.targetNotSubscribable, dbg=err)
                else:
                    err = f'Invalid child resource type: {T(resource.ty).value}'
                    Logging.logWarn(err)
                    return Result(rsc=RC.invalidChildResourceType, dbg=err)

        # if not already set: determine and add the srn
        if resource.__srn__ is None:
            resource[resource._srn] = Utils.structuredPath(resource)

        # add the resource to storage
        if (res := resource.dbCreate(overwrite=False)).rsc != RC.created:
            return res
示例#2
0
	def _handleRequest(self, path:str, operation:Operation) -> Response:
		"""	Get and check all the necessary information from the request and
			build the internal strutures. Then, depending on the operation,
			call the associated request handler.
		"""
		Logging.logDebug(f'==> {operation.name}: /{path}') 	# path = request.path  w/o the root
		Logging.logDebug(f'Headers: \n{str(request.headers)}')
		httpRequestResult = Utils.dissectHttpRequest(request, operation, Utils.retrieveIDFromPath(path, CSE.cseRn, CSE.cseCsi))

		if self.isStopped:
			responseResult = Result(rsc=RC.internalServerError, dbg='http server not running	', status=False)
		else:
			try:
				if httpRequestResult.status:
					if operation in [ Operation.CREATE, Operation.UPDATE ]:
						if httpRequestResult.request.ct == ContentSerializationType.CBOR:
							Logging.logDebug(f'Body: \n{Utils.toHex(httpRequestResult.request.data)}\n=>\n{httpRequestResult.request.dict}')
						else:
							Logging.logDebug(f'Body: \n{str(httpRequestResult.request.data)}')
					responseResult = self._requestHandlers[operation](httpRequestResult.request)
				else:
					responseResult = httpRequestResult
			except Exception as e:
				responseResult = self._prepareException(e)
		responseResult.request = httpRequestResult.request

		return self._prepareResponse(responseResult)
示例#3
0
    def createResource(self,
                       resource: Resource,
                       overwrite: bool = True) -> Result:
        if resource is None:
            Logging.logErr('resource is None')
            raise RuntimeError('resource is None')

        ri = resource.ri

        # Logging.logDebug(f'Adding resource (ty: {resource.ty:d}, ri: {resource.ri}, rn: {resource.rn})'
        srn = resource.__srn__
        if overwrite:
            Logging.logDebug('Resource enforced overwrite')
            self.db.upsertResource(resource)
        else:
            if not self.hasResource(
                    ri, srn):  # Only when not resource does not exist yet
                self.db.insertResource(resource)
            else:
                Logging.logWarn(
                    f'Resource already exists (Skipping): {resource}')
                return Result(status=False,
                              rsc=RC.alreadyExists,
                              dbg='resource already exists')

        # Add path to identifiers db
        self.db.insertIdentifier(resource, ri, srn)
        return Result(status=True, rsc=RC.created)
	def _deleteCSRonRegistrarCSE(self) -> Result:
		Logging.logDebug(f'Deleting registrar CSR: {self.registrarCSI} url: {self.registrarCSRURL}')
		res = CSE.request.sendDeleteRequest(self.registrarCSRURL, CSE.cseCsi, ct=self.registrarSerialization)	# own CSE.csi is the originator
		if res.rsc not in [ RC.deleted, RC.OK ]:
			return Result(rsc=res.rsc, dbg='cannot delete registrar CSR')
		Logging.log(f'Registrar CSR deleted: {self.registrarCSI}')
		return Result(rsc=RC.deleted)
    def retrieveRequest(self, request: CSERequest) -> Result:
        Logging.logDebug(
            f'RETRIEVE ID: {request.id if request.id is not None else request.srn}, originator: {request.headers.originator}'
        )

        # handle transit requests
        if self.isTransitID(request.id):
            return self.handleTransitRetrieveRequest(
                request) if self.enableTransit else Result(
                    rsc=RC.operationNotAllowed, dbg='operation not allowed')

        if request.args.rt == ResponseType.blockingRequest:
            return CSE.dispatcher.processRetrieveRequest(
                request, request.headers.originator)

        elif request.args.rt in [
                ResponseType.nonBlockingRequestSynch,
                ResponseType.nonBlockingRequestAsynch
        ]:
            return self._handleNonBlockingRequest(request)

        elif request.args.rt == ResponseType.flexBlocking:
            if self.flexBlockingBlocking:  # flexBlocking as blocking
                return CSE.dispatcher.processRetrieveRequest(
                    request, request.headers.originator)
            else:  # flexBlocking as non-blocking
                return self._handleNonBlockingRequest(request)

        return Result(
            rsc=RC.badRequest,
            dbg='Unknown or unsupported ResponseType: {request.args.rt}')
	def _retrieveLocalCSRs(self, csi:str=None, onlyOwn:bool=True) -> Result:
		localCsrs = CSE.dispatcher.directChildResources(pi=CSE.cseRi, ty=T.CSR)
		if csi is None:
			csi = self.registrarCSI
		# Logging.logDebug(f'Retrieving local CSR: {csi}')
		if onlyOwn:
			for localCsr in localCsrs:
				if (c := localCsr.csi) is not None and c == csi:
					return Result(lst=[ localCsr ])
			return Result(rsc=RC.badRequest, dbg='local CSR not found')
示例#7
0
 def addSubscription(self, subscription: Resource,
                     originator: str) -> Result:
     if not self.enableNotifications:
         return Result(status=False,
                       rsc=RC.subscriptionVerificationInitiationFailed,
                       dbg='notifications are disabled')
     Logging.logDebug('Adding subscription')
     if (res := self._checkNusInSubscription(subscription,
                                             originator=originator)
         ).lst is None:  # verification requests happen here
         return Result(status=False, rsc=res.rsc, dbg=res.dbg)
 def checkResourceDeletion(self, resource: Resource) -> Result:
     if resource.ty == T.AE:
         if not self.handleAEDeRegistration(resource):
             return Result(status=False, dbg='cannot deregister AE')
     if resource.ty == T.REQ:
         if not self.handleREQDeRegistration(resource):
             return Result(status=False, dbg='cannot deregister REQ')
     if resource.ty == T.CSR:
         if not self.handleCSRDeRegistration(resource):
             return Result(status=False, dbg='cannot deregister CSR')
     return Result(status=True)
示例#9
0
def resourceFromDict(resDict: Dict[str, Any] = {},
                     pi: str = None,
                     ty: T = None,
                     create: bool = False,
                     isImported: bool = False) -> Result:
    """ Create a resource from a dictionary structure.
		This will *not* call the activate method, therefore some attributes
		may be set separately.
	"""
    resDict, tpe = Utils.pureResource(
        resDict)  # remove optional "m2m:xxx" level
    typ = resDict['ty'] if 'ty' in resDict else ty

    # Check whether given type during CREATE matches the resource's ty attribute
    if typ != None and ty != None and typ != ty:
        Logging.logWarn(
            dbg := f'parameter type ({ty}) and resource type ({typ}) mismatch')
        return Result(dbg=dbg, rsc=RC.badRequest)

    # Check whether given type during CREATE matches the resource type specifier
    if ty != None and tpe != None and ty not in [
            T.FCNT, T.FCNTAnnc, T.FCI, T.FCIAnnc, T.MGMTOBJ, T.MGMTOBJAnnc
    ] and ty.tpe() != tpe:
        Logging.logWarn(
            dbg :=
            f'parameter type ({ty}) and resource type specifier ({tpe}) mismatch'
        )
        return Result(dbg=dbg, rsc=RC.badRequest)

    # store the import status in the original resDict
    if isImported:
        resDict[Resource.
                _imported] = True  # Indicate that this is an imported resource

    # Determine a factory and call it
    factory: FactoryT = None
    if typ == T.MGMTOBJ:  # for <mgmtObj>
        mgd = resDict[
            'mgd'] if 'mgd' in resDict else None  # Identify mdg in <mgmtObj>
        factory = resourceFactoryMap.get(mgd)
    elif typ == T.MGMTOBJAnnc:  # for <mgmtObjA>
        mgd = resDict[
            'mgd'] if 'mgd' in resDict else None  # Identify mdg in <mgmtObj>
        factory = resourceFactoryMap.get(
            T.announcedMgd(mgd))  # Get the announced version
    else:
        factory = resourceFactoryMap.get(typ)
    if factory is not None:
        return Result(resource=factory(resDict, tpe, pi, create))

    return Result(resource=Unknown(resDict, tpe, pi=pi,
                                   create=create))  # Capture-All resource
	def _updateCSRonRegistrarCSE(self, localCSE:Resource=None) -> Result:
		Logging.logDebug(f'Updating registrar CSR in CSE: {self.registrarCSI}')
		if localCSE is None:
			localCSE = Utils.getCSE().resource
		csr = CSR.CSR()
		self._copyCSE2CSR(csr, localCSE, isUpdate=True)
		del csr['acpi']			# remove ACPI (don't provide ACPI in updates...a bit)

		res = CSE.request.sendUpdateRequest(self.registrarCSRURL, CSE.cseCsi, data=csr.asDict(), ct=self.registrarSerialization) 	# own CSE.csi is the originator
		if res.rsc not in [ RC.updated, RC.OK ]:
			if res.rsc != RC.alreadyExists:
				Logging.logDebug(f'Error updating registrar CSR in CSE: {res.rsc:d}')
			return Result(rsc=res.rsc, dbg='cannot update remote CSR')
		Logging.logDebug(f'Registrar CSR updated in CSE: {self.registrarCSI}')
		return Result(resource=CSR.CSR(res.dict, pi=''), rsc=RC.updated)
示例#11
0
class ACP(AnnounceableResource):

	def __init__(self, dct:JSON=None, pi:str=None, rn:str=None, create:bool=False, createdInternally:str=None) -> None:
		super().__init__(T.ACP, dct, pi, create=create, inheritACP=True, rn=rn, attributePolicies=attributePolicies)

		self.resourceAttributePolicies = acpPolicies	# only the resource type's own policies
		
		if self.dict is not None:
			self.setAttribute('pv/acr', [], overwrite=False)
			self.setAttribute('pvs/acr', [], overwrite=False)
			if createdInternally is not None:
				self.setCreatedInternally(createdInternally)


	# Enable check for allowed sub-resources
	def canHaveChild(self, resource:Resource) -> bool:
		return super()._canHaveChild(resource,	
									 [ T.SUB # TODO Transaction to be added
									 ])





	def validate(self, originator:str=None, create:bool=False, dct:JSON=None) -> Result:
		if not (res := super().validate(originator, create, dct)).status:
			return res
		
		if dct is not None and (pvs := Utils.findXPath(dct, f'{T.ACPAnnc.tpe()}/pvs')) is not None:
			if len(pvs) == 0:
				return Result(status=False, rsc=RC.badRequest, dbg='pvs must not be empty')
示例#12
0
class DVC(MgmtObj):

	def __init__(self, dct:JSON=None, pi:str=None, create:bool=False) -> None:
		self.resourceAttributePolicies = dvcPolicies	# only the resource type's own policies
		super().__init__(dct, pi, mgd=T.DVC, create=create, attributePolicies=attributePolicies)

		if self.dict is not None:
			self.setAttribute('can', 'unknown', overwrite=False)
			self.setAttribute('att', False, overwrite=False)
			self.setAttribute('cas', {	"acn" : "unknown", "sus" : 0 }, overwrite=False)
			self.setAttribute('cus', False, overwrite=False)
			self.setAttribute('ena', True, overwrite=True)	# always True
			self.setAttribute('dis', True, overwrite=True)	# always True

	#
	#	Handling the special behaviour for ena and dis attributes in 
	#	validate() and update()
	#

	def validate(self, originator:str=None, create:bool=False, dct:JSON=None) -> Result:
		if not (res := super().validate(originator, create, dct)).status:
			return res
		self.setAttribute('ena', True, overwrite=True)	# always set (back) to True
		self.setAttribute('dis', True, overwrite=True)	# always set (back) to True
		return Result(status=True)
示例#13
0
class PCH(Resource):
    def __init__(self,
                 dct: JSON = None,
                 pi: str = None,
                 create: bool = False) -> None:
        super().__init__(T.PCH,
                         dct,
                         pi,
                         create=create,
                         attributePolicies=attributePolicies)
        self.resourceAttributePolicies = pchPolicies  # only the resource type's own policies

    # Enable check for allowed sub-resources
    def canHaveChild(self, resource: Resource) -> bool:
        return super()._canHaveChild(resource, [T.PCH_PCU])

# TODO test Retrieve by AE only! Add new willBeRetrieved() function
# TODO continue with 10.2.5.14 Retrieve <pollingChannel>

    def activate(self, parentResource: Resource, originator: str) -> Result:
        if not (res := super().activate(parentResource, originator)).status:
            return res

        # NOTE Check for uniqueness is done in <AE>.childWillBeAdded()
        # TODO the same for CSR

        # register pollingChannelURI virtual resource
        Logging.logDebug(f'Registering <PCU> for: {self.ri}')
        pcu = Factory.resourceFromDict(
            pi=self.ri,
            ty=T.PCH_PCU).resource  # rn is assigned by resource itself
        if (res := CSE.dispatcher.createResource(pcu)).resource is None:
            return Result(status=False, rsc=res.rsc, dbg=res.dbg)
示例#14
0
	def update(self, dct:JSON=None, originator:str=None) -> Result:
		dictOrg = deepcopy(self.dict)	# Save for later for notification

		updatedAttributes = None
		if dct is not None:
			if self.tpe not in dct and self.ty not in [T.FCNTAnnc, T.FCIAnnc]:	# Don't check announced versions of announced FCNT
				Logging.logWarn("Update type doesn't match target")
				return Result(status=False, rsc=RC.contentsUnacceptable, dbg='resource types mismatch')


			# validate the attributes
			if not (res := CSE.validator.validateAttributes(dct, self.tpe, self.attributePolicies, create=False, createdInternally=self.isCreatedInternally(), isAnnounced=self.isAnnounced())).status:
				return res

			if self.ty not in [T.FCNTAnnc, T.FCIAnnc]:
				updatedAttributes = dct[self.tpe] # get structure under the resource type specifier
			else:
				updatedAttributes = Utils.findXPath(dct, '{0}')

			# Check that acpi, if present, is the only attribute
			if 'acpi' in updatedAttributes:	# No further checks here. This has been done before in the Dispatcher.processUpdateRequest()	

				# Check whether referenced <ACP> exists. If yes, change ID also to CSE relative unstructured
				if not (res := self._checkAndFixACPIreferences(updatedAttributes['acpi'])).status:
					return res
				
				self.setAttribute('acpi', res.lst, overwrite=True) # copy new value or add new attributes
示例#15
0
class CNT_OL(Resource):
    def __init__(self,
                 dct: JSON = None,
                 pi: str = None,
                 create: bool = False) -> None:
        super().__init__(T.CNT_OL,
                         dct,
                         pi,
                         create=create,
                         inheritACP=True,
                         readOnly=True,
                         rn='ol',
                         isVirtual=True)

    # Enable check for allowed sub-resources
    def canHaveChild(self, resource: Resource) -> bool:
        return super()._canHaveChild(resource, [])

    def handleRetrieveRequest(self,
                              request: CSERequest = None,
                              id: str = None,
                              originator: str = None) -> Result:
        """ Handle a RETRIEVE request. Return resource """
        Logging.logDebug('Retrieving oldest CIN from CNT')
        if (r := self._getOldest()) is None:
            return Result(rsc=RC.notFound, dbg='no instance for <oldest>')
        return Result(resource=r)
示例#16
0
    def validatePvs(self, dct: JSON) -> Result:
        """ Validating special case for lists that are not allowed to be empty (pvs in ACP). """

        if (l := len(dct['pvs'])) == 0:
            err = 'Attribute pvs must not be an empty list'
            Logging.logWarn(err)
            return Result(status=False, dbg=err)
示例#17
0
class CSEBase(Resource):
    def __init__(self, dct: JSON = None, create: bool = False) -> None:
        super().__init__(T.CSEBase,
                         dct,
                         '',
                         create=create,
                         attributePolicies=attributePolicies)

        if self.dict is not None:
            self.setAttribute('ri', 'cseid', overwrite=False)
            self.setAttribute('rn', 'cse', overwrite=False)
            self.setAttribute('csi', 'cse', overwrite=False)

            self.setAttribute('rr', False, overwrite=False)
            self.setAttribute('srt', C.supportedResourceTypes, overwrite=False)
            self.setAttribute('csz',
                              C.supportedContentSerializations,
                              overwrite=False)
            self.setAttribute('srv',
                              CSE.supportedReleaseVersions,
                              overwrite=False)  # This must be a list
            self.setAttribute('poa', [CSE.httpServer.serverAddress],
                              overwrite=False
                              )  # TODO add more address schemes when available
            self.setAttribute('cst', CSE.cseType, overwrite=False)

    # Enable check for allowed sub-resources
    def canHaveChild(self, resource: Resource) -> bool:
        return super()._canHaveChild(
            resource,
            [T.ACP, T.AE, T.CSR, T.CNT, T.FCNT, T.GRP, T.NOD, T.REQ, T.SUB])

    def validate(self,
                 originator: str = None,
                 create: bool = False,
                 dct: JSON = None) -> Result:
        if not (res := super().validate(originator, create, dct)).status:
            return res

        self.normalizeURIAttribute('poa')

        # Update the hcl attribute in the hosting node (similar to AE)
        nl = self['nl']
        _nl_ = self.__node__

        if nl is not None or _nl_ is not None:
            if nl != _nl_:
                if _nl_ is not None:
                    nresource = CSE.dispatcher.retrieveResource(_nl_).resource
                    if nresource is not None:
                        nresource['hcl'] = None  # remove old link
                        CSE.dispatcher.updateResource(nresource)
                self[Resource._node] = nl
                nresource = CSE.dispatcher.retrieveResource(nl)
                if nresource is not None:
                    nresource['hcl'] = self['ri']
                    CSE.dispatcher.updateResource(nresource)
            self[Resource._node] = nl

        return Result(status=True)
示例#18
0
class RBO(MgmtObj):
    def __init__(self,
                 dct: JSON = None,
                 pi: str = None,
                 create: bool = False) -> None:
        self.resourceAttributePolicies = rboPolicies  # only the resource type's own policies
        super().__init__(dct,
                         pi,
                         mgd=T.RBO,
                         create=create,
                         attributePolicies=attributePolicies)

        if self.dict is not None:
            self.setAttribute('rbo', False, overwrite=True)  # always False
            self.setAttribute('far', False, overwrite=True)  # always False

    #
    #	Handling the special behaviour for rbo and far attributes in
    #	validate() and update()
    #

    def validate(self,
                 originator: str = None,
                 create: bool = False,
                 dct: JSON = None) -> Result:
        if not (res := super().validate(originator, create, dct)).status:
            return res
        self.setAttribute('rbo', False,
                          overwrite=True)  # always set (back) to True
        self.setAttribute('far', False,
                          overwrite=True)  # always set (back) to True
        return Result(status=True)
示例#19
0
 def updateSubscription(self, subscription: Resource, newDict: JSON,
                        previousNus: list[str], originator: str) -> Result:
     Logging.logDebug('Updating subscription')
     #previousSub = CSE.storage.getSubscription(subscription.ri)
     if (res := self._checkNusInSubscription(
             subscription, newDict, previousNus, originator=originator)
         ).lst is None:  # verification/delete requests happen here
         return Result(status=False, rsc=res.rsc, dbg=res.dbg)
示例#20
0
 def handleRetrieveRequest(self,
                           request: CSERequest = None,
                           id: str = None,
                           originator: str = None) -> Result:
     """ Handle a RETRIEVE request. Return resource """
     Logging.logDebug('Retrieving oldest CIN from CNT')
     if (r := self._getOldest()) is None:
         return Result(rsc=RC.notFound, dbg='no instance for <oldest>')
	def _deleteLocalCSR(self, localCSR: Resource) -> Result:
		Logging.logDebug(f'Deleting local CSR: {localCSR.ri}')

		if not CSE.registration.handleCSRDeRegistration(localCSR):
			return Result(rsc=RC.badRequest, dbg='cannot deregister CSR')

		# Delete local CSR
		return CSE.dispatcher.deleteResource(localCSR)
示例#22
0
 def updateResource(self, resource: Resource) -> Result:
     if resource is None:
         Logging.logErr('resource is None')
         raise RuntimeError('resource is None')
     ri = resource.ri
     # Logging.logDebug(f'Updating resource (ty: {resource.ty:d}, ri: {ri}, rn: {resource.rn})')
     return Result(resource=self.db.updateResource(resource),
                   rsc=RC.updated)
示例#23
0
 def deleteResource(self, resource: Resource) -> Result:
     if resource is None:
         Logging.logErr('resource is None')
         raise RuntimeError('resource is None')
     # Logging.logDebug(f'Removing resource (ty: {resource.ty:d}, ri: {ri}, rn: {resource.rn})'
     self.db.deleteResource(resource)
     self.db.deleteIdentifier(resource)
     return Result(status=True, rsc=RC.deleted)
 def checkResourceCreation(self,
                           resource: Resource,
                           originator: str,
                           parentResource: Resource = None) -> Result:
     if resource.ty == T.AE:
         if (originator := self.handleAERegistration(
                 resource, originator, parentResource).originator
             ) is None:  # assigns new originator
             return Result(rsc=RC.badRequest, dbg='cannot register AE')
    def handleCreator(self, resource: Resource, originator: str) -> Result:
        """	Check for set creator attribute as well as assign it to allowed resources.
		"""
        if resource.hasAttribute('cr'):
            if resource.ty not in C.creatorAllowed:
                return Result(
                    rsc=RC.badRequest,
                    dbg=
                    f'"creator" attribute is not allowed for resource type: {resource.ty}'
                )
            if resource.cr is not None:  # Check whether cr is set to a value. This is wrong
                Logging.logWarn('Setting "creator" attribute is not allowed.')
                return Result(rsc=RC.badRequest,
                              dbg='setting "creator" attribute is not allowed')
            else:
                resource['cr'] = originator
                # fall-through
        return Result()  # implicit OK
示例#26
0
	def update(self, dct:JSON=None, originator:str=None) -> Result:
		# Check for ena & dis updates 
		if dct is not None and self.tpe in dct:
			ena = Utils.findXPath(dct, 'm2m:dvc/ena')
			dis = Utils.findXPath(dct, 'm2m:dvc/dis')
			if ena is not None and dis is not None and ena and dis:
				return Result(status=False, rsc=RC.badRequest, dbg='both ena and dis updated to True is not allowed')

		return super().update(dct, originator)
示例#27
0
class AE(AnnounceableResource):
    def __init__(self,
                 dct: JSON = None,
                 pi: str = None,
                 create: bool = False) -> None:
        super().__init__(T.AE,
                         dct,
                         pi,
                         create=create,
                         attributePolicies=attributePolicies)

        self.resourceAttributePolicies = aePolicies  # only the resource type's own policies

        if self.dict is not None:
            self.setAttribute('aei', Utils.uniqueAEI(), overwrite=False)
            self.setAttribute('rr', False, overwrite=False)

    # Enable check for allowed sub-resources
    def canHaveChild(self, resource: Resource) -> bool:
        return super()._canHaveChild(
            resource, [T.ACP, T.CNT, T.FCNT, T.GRP, T.PCH, T.SUB])

    def childWillBeAdded(self, childResource: Resource,
                         originator: str) -> Result:
        if not (res := super().childWillBeAdded(childResource,
                                                originator)).status:
            return res

        # Perform checks for <PCH>
        if childResource.ty == T.PCH:
            # Check correct originator. Even the ADMIN is not allowed that
            if self.aei != originator:
                Logging.logDebug(dbg := f'Originator must be the parent <AE>')
                return Result(status=False,
                              rsc=RC.originatorHasNoPrivilege,
                              dbg=dbg)

            # check that there will only by one PCH as a child
            if CSE.dispatcher.countDirectChildResources(self.ri, ty=T.PCH) > 0:
                return Result(status=False,
                              rsc=RC.badRequest,
                              dbg='Only one PCH per AE is allowed')

        return Result(status=True)
示例#28
0
class NotificationManager(object):
    def __init__(self) -> None:
        self.lockBatchNotification = Lock()  # Lock for batchNotifications
        self.enableNotifications = Configuration.get('cse.enableNotifications')

        if self.enableNotifications:
            Logging.log('Notifications ENABLED')
        else:
            Logging.log('Notifications DISABLED')
        Logging.log('NotificationManager initialized')

    def shutdown(self) -> bool:
        Logging.log('NotificationManager shut down')
        return True

    ###########################################################################
    #
    #	Subscriptions
    #

    # def addSubscription(self, subscription:Resource, originator:str) -> Result:
    # 	if not self.enableNotifications:
    # 		return Result(status=False, rsc=RC.subscriptionVerificationInitiationFailed, dbg='notifications are disabled')
    # 	Logging.logDebug('Adding subscription')
    # 	if (res := self._checkNusInSubscription(subscription, originator=originator)).lst is None:	# verification requests happen here
    # 		return Result(status=False, rsc=res.rsc, dbg=res.dbg)
    # 	return Result(status=True) if CSE.storage.addSubscription(subscription) else Result(status=False, rsc=RC.internalServerError, dbg='cannot add subscription to database')

    def addSubscription(self, subscription: Resource,
                        originator: str) -> Result:
        if not self.enableNotifications:
            return Result(status=False,
                          rsc=RC.subscriptionVerificationInitiationFailed,
                          dbg='notifications are disabled')
        Logging.logDebug('Adding subscription')
        if (res := self._checkNusInSubscription(subscription,
                                                originator=originator)
            ).lst is None:  # verification requests happen here
            return Result(status=False, rsc=res.rsc, dbg=res.dbg)
        return Result(status=True) if CSE.storage.addSubscription(
            subscription) else Result(
                status=False,
                rsc=RC.internalServerError,
                dbg='cannot add subscription to database')
    def hasAcpiUpdatePermission(self, request: CSERequest,
                                targetResource: Resource,
                                originator: str) -> Result:
        """	Check whether this is actually a correct update of the acpi attribute, and whether this is actually allowed.
		"""
        updatedAttributes = Utils.findXPath(request.dict, '{0}')

        # Check that acpi, if present, is the only attribute
        if 'acpi' in updatedAttributes:
            if len(updatedAttributes) > 1:
                Logging.logDebug(
                    dbg := '"acpi" must be the only attribute in update')
                return Result(status=False, rsc=RC.badRequest, dbg=dbg)

            # Check whether the originator has UPDATE privileges for the acpi attribute (pvs!)
            if targetResource.acpi is None:
                if originator != targetResource[targetResource._originator]:
                    Logging.logDebug(
                        dbg :=
                        f'No access to update acpi for originator: {originator}'
                    )
                    return Result(status=False,
                                  rsc=RC.originatorHasNoPrivilege,
                                  dbg=dbg)
                else:
                    pass  # allowed for creating originator
            else:
                # test the current acpi whether the originator is allowed to update the acpi
                for ri in targetResource.acpi:
                    if (acp := CSE.dispatcher.retrieveResource(ri).resource
                        ) is None:
                        Logging.logWarn(
                            f'Access Check for acpi: referenced <ACP> resource not found: {ri}'
                        )
                        continue
                    if acp.checkSelfPermission(originator, Permission.UPDATE):
                        break
                else:
                    Logging.logDebug(
                        dbg :=
                        f'Originator has no permission to update acpi: {ri}')
                    return Result(status=False,
                                  rsc=RC.originatorHasNoPrivilege,
                                  dbg=dbg)
示例#30
0
    def foptRequest(self, operation: Operation, fopt: GRP_FOPT,
                    request: CSERequest, id: str, originator: str) -> Result:
        """	Handle requests to a fanOutPoint. 
		This method might be called recursivly, when there are groups in groups."""

        # get parent / group and check permissions
        group = fopt.retrieveParentResource()
        if group is None:
            return Result(rsc=RC.notFound, dbg='group resource not found')

        # get the permission flags for the request operation
        permission = operation.permission()

        #check access rights for the originator through memberAccessControlPolicies
        if CSE.security.hasAccess(originator,
                                  group,
                                  requestedPermission=permission,
                                  ty=request.headers.resourceType,
                                  isCreateRequest=True if operation
                                  == Operation.CREATE else False) == False:
            return Result(rsc=RC.originatorHasNoPrivilege, dbg='access denied')

        # check whether there is something after the /fopt ...
        _, _, tail = id.partition('/fopt/') if '/fopt/' in id else (None, None,
                                                                    '')
        Logging.logDebug(f'Adding additional path elements: {tail}')

        # walk through all members
        resultList: list[Result] = []

        tail = '/' + tail if len(
            tail) > 0 else ''  # add remaining path, if any
        for mid in group.mid.copy(
        ):  # copy mi because it is changed in the loop
            # Try to get the SRN and add the tail
            if (srn := Utils.structuredPathFromRI(mid)) is not None:
                mid = srn + tail
            else:
                mid = mid + tail
            # Invoke the request
            if operation == Operation.RETRIEVE:
                if (res := CSE.dispatcher.processRetrieveRequest(
                        request, originator, mid)).resource is None:
                    return res