def find_user_info_by_subject(self, subject=''): # Find UserCredentials objects, matches = self.clients.resource_registry.find_resources( RT.UserCredentials, None, subject, id_only=False) if not objects: raise NotFound("UserCredentials with subject %s does not exist" % subject) if len(objects) > 1: raise Inconsistent( "Multiple UserCredentials with subject %s exist" % subject) user_credentials_id = objects[0]._id subjects, assocs = self.clients.resource_registry.find_subjects( RT.ActorIdentity, PRED.hasCredentials, user_credentials_id) if not subjects or len(subjects) == 0: raise NotFound( "ActorIdentity to UserCredentials association for subject %s does not exist" % subject) if len(subjects) > 1: raise Inconsistent( "Multiple ActorIdentity to UserCredentials associations for subject %s exist" % subject) actor_identity_id = subjects[0]._id # Look up UserInfo via association with ActorIdentity objects, assocs = self.clients.resource_registry.find_objects( actor_identity_id, PRED.hasInfo, RT.UserInfo) if not objects: raise NotFound("UserInfo for subject %s does not exist" % subject) if len(objects) > 1: raise Inconsistent("Multiple UserInfos for subject %s exist" % subject) user_info = objects[0] return user_info
def handle_incoming_message(self, invocation): receiver = invocation.get_message_receiver() op = invocation.get_header_value('op', 'Unknown') actor_id = invocation.get_header_value(MSG_HEADER_ACTOR, 'anonymous') # Raise Inconsistent message if conversation interceptor found a problem # TODO - May just want to drop this message instead of returning in case of DOS attack if GovernanceDispatcher.CONVERSATION__STATUS_ANNOTATION in invocation.message_annotations and \ invocation.message_annotations[GovernanceDispatcher.CONVERSATION__STATUS_ANNOTATION] == GovernanceDispatcher.STATUS_REJECT: if GovernanceDispatcher.CONVERSATION__STATUS_REASON_ANNOTATION in invocation.message_annotations: raise Inconsistent( "The message from user %s for operation %s(%s) has an error: %s" % (actor_id, receiver, op, invocation.message_annotations[ GovernanceDispatcher. CONVERSATION__STATUS_REASON_ANNOTATION])) else: raise Inconsistent( "The message from user %s for operation %s(%s) is inconsistent with the specified protocol" % (actor_id, receiver, op)) # Raise Unauthorized exception if policy denies access. if GovernanceDispatcher.POLICY__STATUS_ANNOTATION in invocation.message_annotations and \ invocation.message_annotations[GovernanceDispatcher.POLICY__STATUS_ANNOTATION] == GovernanceDispatcher.STATUS_REJECT: if GovernanceDispatcher.POLICY__STATUS_REASON_ANNOTATION in invocation.message_annotations: raise Unauthorized(invocation.message_annotations[ GovernanceDispatcher.POLICY__STATUS_REASON_ANNOTATION]) raise Unauthorized( "The request from user %s for operation %s(%s) has been denied" % (actor_id, receiver, op)) return invocation
def _analyze_objects(self, resources_objs): for obj_id, key, obj in resources_objs: if obj_id.startswith("_design"): continue if not isinstance(obj, dict): raise Inconsistent("Object of bad type found: %s" % type(obj)) obj_type = obj.get("type_", None) if obj_type == "Association": self._associations[obj_id] = obj elif obj_type == "DirEntry": self._directory[obj_id] = obj elif obj_type: self._resources[obj_id] = obj if obj_type not in self._res_by_type: self._res_by_type[obj_type] = [] self._res_by_type[obj_type].append(obj_id) for attr, value in obj.iteritems(): if obj_type not in self._attr_by_type: self._attr_by_type[obj_type] = set() self._attr_by_type[obj_type].add(attr) else: raise Inconsistent("Object with no type_ found: %s" % obj) for assoc in self._associations.values(): key = (assoc['s'], assoc['p']) if key not in self._assoc_by_sub: self._assoc_by_sub[key] = [] self._assoc_by_sub[key].append(assoc['o'])
def create_transform_process(self, data_process_definition_id, data_process_input_dp_id, stream_name): data_process_definition = self.rrclient.read( data_process_definition_id) # Find the link between the output Stream Definition resource and the Data Process Definition resource stream_ids, _ = self.rrclient.find_objects(data_process_definition._id, PRED.hasStreamDefinition, RT.StreamDefinition, id_only=True) if not stream_ids: raise Inconsistent( "The data process definition %s is missing an association to an output stream definition" % data_process_definition._id) process_output_stream_def_id = stream_ids[0] #Concatenate the name of the workflow and data process definition for the name of the data product output data_process_name = data_process_definition.name # Create the output data product of the transform tdom, sdom = time_series_domain() transform_dp_obj = IonObject( RT.DataProduct, name=data_process_name, description=data_process_definition.description, temporal_domain=tdom.dump(), spatial_domain=sdom.dump()) transform_dp_id = self.dataproductclient.create_data_product( transform_dp_obj, process_output_stream_def_id) self.dataproductclient.activate_data_product_persistence( data_product_id=transform_dp_id) #last one out of the for loop is the output product id output_data_product_id = transform_dp_id # Create the transform data process log.debug("create data_process and start it") data_process_id = self.dataprocessclient.create_data_process( data_process_definition._id, [data_process_input_dp_id], {stream_name: transform_dp_id}) self.dataprocessclient.activate_data_process(data_process_id) #Find the id of the output data stream stream_ids, _ = self.rrclient.find_objects(transform_dp_id, PRED.hasStream, None, True) if not stream_ids: raise Inconsistent( "The data process %s is missing an association to an output stream" % data_process_id) return data_process_id, output_data_product_id
def execute_replay(self): ''' @brief Spawns a greenlet to take care of the query and work ''' if not hasattr(self, 'output'): raise Inconsistent( 'The replay process requires an output stream publisher named output. Invalid configuration!' ) datastore_name = self.datastore_name key_id = self.key_id view_name = self.view_name opts = { 'start_key': [key_id, 0], 'end_key': [key_id, 2], 'include_docs': True } g = Greenlet(self._query, datastore_name=datastore_name, view_name=view_name, opts=opts, callback=lambda results: self._publish_query(results)) g.start()
def create_policy(self, policy=None): """Persists the provided Policy object The id string returned is the internal id by which Policy will be identified in the data store. @param policy Policy @retval policy_id str @throws BadRequest if object passed has _id or _rev attribute """ if not policy: raise BadRequest("The policy parameter is missing") if not is_basic_identifier(policy.name): raise BadRequest( "The policy name '%s' can only contain alphanumeric and underscore characters" % policy.name) try: #If there is a policy_rule field then try to add the policy name and decription to the rule text if hasattr(policy.policy_type, 'policy_rule'): policy.policy_type.policy_rule = policy.policy_type.policy_rule % ( policy.name, policy.description) except Exception, e: raise Inconsistent( "Missing the elements in the policy rule to set the description: " + e.message)
def read_subject(self, subject_type="", predicate="", object="", assoc="", id_only=False): if assoc: if type(assoc) is str: assoc = self.read(assoc) return assoc.s if id_only else self.read(assoc.s) else: sub_list, assoc_list = self.find_subjects( subject_type=subject_type, predicate=predicate, object=object, id_only=True) if not sub_list: raise NotFound( "No subject found for subject_type=%s, predicate=%s, object=%s" % (subject_type, predicate, object)) elif len(sub_list) > 1: raise Inconsistent( "More than one subject found for subject_type=%s, predicate=%s, object=%s: count=%s" % (subject_type, predicate, object, len(sub_list))) return sub_list[0] if id_only else self.read(sub_list[0])
def _find_org_roles_by_user(self, org=None, user=None): if org is None: raise BadRequest("The org parameter is missing") if user is None: raise BadRequest("The user parameter is missing") role_list, _ = self.clients.resource_registry.find_objects( user, PRED.hasRole, RT.UserRole) #Iterate the list of roles associated with user and filter by the org_id. TODO - replace this when #better indexing/views are available in couch ret_list = [] for role in role_list: if role.org_id == org._id: ret_list.append(role) #Because a user is enrolled with an Org then the membership role is implied - so add it to the list member_role = self._find_role(org._id, MEMBER_ROLE) if member_role is None: raise Inconsistent('The %s User Role is not found.' % MEMBER_ROLE) ret_list.append(member_role) return ret_list
def set_object_field(obj, field, field_val): if isinstance(field_val, dict) and field != 'kwargs': sub_obj = getattr(obj, field) if isinstance(sub_obj, IonObjectBase): if field_val.has_key( 'type_') and field_val['type_'] != sub_obj.type_: if issubtype(field_val['type_'], sub_obj.type_): sub_obj = IonObject(field_val['type_']) setattr(obj, field, sub_obj) else: raise Inconsistent( "Unable to walk the field %s as an IonObject since the types don't match: %s %s" % (field, sub_obj.type_, field_val['type_'])) for sub_field in field_val: set_object_field(sub_obj, sub_field, field_val.get(sub_field)) elif isinstance(sub_obj, dict): setattr(obj, field, field_val) else: for sub_field in field_val: set_object_field(sub_obj, sub_field, field_val.get(sub_field)) else: # type_ already exists in the class. if field != "type_": setattr(obj, field, field_val)
def find_user_info_by_name(self, name=''): objects, matches = self.clients.resource_registry.find_resources(RT.UserInfo, None, name, id_only=False) if not objects: raise NotFound("UserInfo with name %s does not exist" % name) if len(objects) > 1: raise Inconsistent("Multiple UserInfo objects with name %s exist" % name) return objects[0]
def test_find_fun(self): """ self is an instance of the tester class """ # get objects svc = self._rimi_getservice() myimpl = getattr(svc, impl_attr) # put in 2 objects sr = sample_resource() sample_resource_id = myimpl.create_one(sr) sr2 = sample_resource() sr2.name = "NOT A DUPE" sample_resource_id2 = myimpl.create_one(sr2) resources = myimpl.find_some({}) self.assertIsInstance(resources, list) self.assertNotEqual(0, len(resources)) self.assertNotEqual(1, len(resources)) resource_ids = [] for r in resources: if not "_id" in r: raise Inconsistent("'_id' field not found in resource! got: %s" % str(r)) resource_ids.append(r._id) self.assertIn(sample_resource_id, resource_ids) self.assertIn(sample_resource_id2, resource_ids) if all_in_one: myimpl.delete_one(sample_resource_id) myimpl.delete_one(sample_resource_id2)
def dump_dicts_as_xlsx(self, objects, filename=None): self._clear() """Dumps a dict of dicts. Tab names will be the names of keys in the objects dict""" self._wb = xlwt.Workbook() self._worksheets = {} for cat_name, cat_objects in objects.iteritems(): for obj_id, obj in cat_objects.iteritems(): if not isinstance(obj, dict): raise Inconsistent("Object of bad type found: %s" % type(obj)) self._resources[obj_id] = obj if cat_name not in self._res_by_type: self._res_by_type[cat_name] = [] self._res_by_type[cat_name].append(obj_id) for attr, value in obj.iteritems(): if cat_name not in self._attr_by_type: self._attr_by_type[cat_name] = set() self._attr_by_type[cat_name].add(attr) for restype in sorted(self._res_by_type.keys()): self._dump_resource_type(restype) dtstr = datetime.datetime.today().strftime('%Y%m%d_%H%M%S') path = filename or "interface/objects_%s.xls" % dtstr self._wb.save(path)
def ret_fn(obj_id, subj_id): log.info("Dynamically creating association %s -> %s -> (1)%s", isubj, ipred, iobj) # see if there are any other objects of this type and pred on this subject existing_objs, _ = self.RR.find_objects(subj_id, ipred, iobj, id_only=True) if len(existing_objs) > 1: raise Inconsistent( "Multiple %s-%s objects found with the same %s subject with id='%s'" % (ipred, iobj, isubj, subj_id)) if len(existing_objs) > 0: try: log.debug("get_association gives") log.debug( self.RR.get_association(subj_id, ipred, obj_id)) except NotFound: raise BadRequest( "Attempted to add a second %s-%s association to a %s with id='%s'" % (ipred, iobj, isubj, subj_id)) else: log.debug( "Create %s Association (single object): ALREADY EXISTS", ipred) return self.RR.create_association(subj_id, ipred, obj_id)
def get_predicate_type_list(): Predicates.clear() assoc_defs = Config(["res/config/associations.yml"]).data['AssociationDefinitions'] for ad in assoc_defs: if ad['predicate'] in Predicates: raise Inconsistent('Predicate %s defined multiple times in associations.yml' % ad['predicate']) Predicates[ad['predicate']] = ad return Predicates.keys()
def add_process_operation_precondition_policy(self, process_name='', op='', policy_content=''): """Helper operation for adding a precondition policy for a specific process operation; could be a service or agent. The id string returned is the internal id by which Policy will be identified in the data store. The precondition method must return a tuple (boolean, string). @param process_name str @param op str @param policy_content str @retval policy_id str @throws BadRequest If any of the parameters are not set. """ if not process_name: raise BadRequest("The process_name parameter is missing") if not op: raise BadRequest("The op parameter is missing") if not policy_content: raise BadRequest("The policy_content parameter is missing") policy_name = process_name + "_" + op + "_Precondition_Policies" policies,_ = self.clients.resource_registry.find_resources(restype=RT.Policy, name=policy_name) if policies: #Update existing policy by adding to list if len(policies) > 1: raise Inconsistent('There should only be one Policy object per process_name operation') if policies[0].policy_type.op != op or policies[0].policy_type.type_ != OT.ProcessOperationPreconditionPolicy: raise Inconsistent('There Policy object %s does not match the requested process operation %s: %s' % ( policies[0].name, process_name, op )) policies[0].policy_type.preconditions.append(policy_content) self.update_policy(policies[0]) return policies[0]._id else: #Create a new policy object op_policy_obj = IonObject(OT.ProcessOperationPreconditionPolicy, process_name=process_name, op=op) op_policy_obj.preconditions.append(policy_content) policy_obj = IonObject(RT.Policy, name=policy_name, policy_type=op_policy_obj, description='List of operation precondition policies for ' + process_name) return self.create_policy(policy_obj)
def generic_association_script(self, assign_obj_to_subj_fn, find_subj_fn, find_obj_fn, subj_id, obj_id): """ create an association and test that it went properly @param assign_obj_to_subj_fn the service method that takes (obj, subj) and associates them @param find_subj_fn the service method that returns a list of subjects given an object @param find_obj_fn the service method that returns a list of objects given a subject @param subj_id the subject id to associate @param obj_id the object id to associate """ initial_subj_count = len(find_subj_fn(obj_id)) initial_obj_count = len(find_obj_fn(subj_id)) log.debug("Creating association") if not ("str" == type(subj_id).__name__ == type(obj_id).__name__): raise NotImplementedError( "%s='%s' to %s='%s'" % (type(subj_id), str(subj_id), type(obj_id), str(obj_id))) if not (subj_id and obj_id): raise NotImplementedError( "%s='%s' to %s='%s'" % (type(subj_id), str(subj_id), type(obj_id), str(obj_id))) assign_obj_to_subj_fn(obj_id, subj_id) log.debug("Verifying find-subj-by-obj") subjects = find_subj_fn(obj_id) self.assertEqual(initial_subj_count + 1, len(subjects)) subject_ids = [] for x in subjects: if not "_id" in x: raise Inconsistent( "'_id' field not found in resource! got: %s" % str(x)) subject_ids.append(x._id) self.assertIn(subj_id, subject_ids) log.debug("Verifying find-obj-by-subj") objects = find_obj_fn(subj_id) self.assertEqual(initial_obj_count + 1, len(objects)) object_ids = [] for x in objects: if not "_id" in x: raise Inconsistent( "'_id' field not found in resource! got: %s" % str(x)) object_ids.append(x._id) self.assertIn(obj_id, object_ids)
def create_negotiation(self, sap=None): if sap is None or ( sap.type_ != OT.ServiceAgreementProposal and not issubtype(sap.type_, OT.ServiceAgreementProposal)): raise BadRequest('The sap parameter must be a valid Service Agreement Proposal object') if sap.proposal_status != ProposalStatusEnum.INITIAL or sap.sequence_num != 0: raise Inconsistent('The specified Service Agreement Proposal has inconsistent status fields') if sap.negotiation_id != '': raise Inconsistent('The specified Service Agreement Proposal cannot have a negotiation_id for an initial proposal') if self.negotiation_rules.has_key(sap.type_): #validate preconditions before creating for pc in self.negotiation_rules[sap.type_]['pre_conditions']: if pc.startswith('not '): pre_condition_met = not eval("self.service_provider." + pc.lstrip('not ')) #Strip off the 'not ' part else: pre_condition_met = eval("self.service_provider."+pc) if not pre_condition_met: raise BadRequest("A precondition for this request has not been satisfied: %s" % pc) #Should be able to determine the negotiation type based on the intial originator neg_type = NegotiationTypeEnum.REQUEST if sap.originator == ProposalOriginatorEnum.PROVIDER: neg_type = NegotiationTypeEnum.INVITATION elif sap.originator == ProposalOriginatorEnum.BROKER: neg_type = NegotiationTypeEnum.BROKERED neg_obj = IonObject(RT.Negotiation, negotiation_type=neg_type) #If there is a description in the initial proposal, then set the negotiation description with it. if sap.description != '': neg_obj.description = sap.description neg_id,_ = self.service_provider.clients.resource_registry.create(neg_obj) #Create associations between the parties self.service_provider.clients.resource_registry.create_association(sap.consumer, PRED.hasNegotiation, neg_id) self.service_provider.clients.resource_registry.create_association(sap.provider, PRED.hasNegotiation, neg_id) if sap.broker != "": self.service_provider.clients.resource_registry.create_association(sap.broker, PRED.hasNegotiation, neg_id) return neg_id
def __init__(self, headers, process=None, resource_id_required=True): """ Helpers for retrieving governance related values: op, actor_id, actor_roles, resource_id from the message header @param headers: @param resource_id_required: True if the message header must have a resource-id field and value. """ if not headers or not isinstance(headers, dict): raise BadRequest("The headers parameter is not a valid message header dictionary") self._op = headers.get(MSG_HEADER_OP, "Unknown-Operation") if process is not None and hasattr(process, 'name'): self._process_name = process.name else: if 'process' in headers: if getattr(headers['process'], 'name'): self._process_name = headers['process'].name else: self._process_name = "Unknown-Process" else: self._process_name = "Unknown-Process" # The self.name references below should be provided by the running ION process (service, agent, etc), # which will be using this class. if MSG_HEADER_ACTOR in headers: self._actor_id = headers[MSG_HEADER_ACTOR] else: raise Inconsistent('%s(%s) has been denied since the ion-actor-id can not be found in the message headers' % (self._process_name, self._op)) if MSG_HEADER_ROLES in headers: self._actor_roles = headers[MSG_HEADER_ROLES] else: raise Inconsistent('%s(%s) has been denied since the ion-actor-roles can not be found in the message headers' % (self._process_name, self._op)) if MSG_HEADER_RESOURCE_ID in headers: self._resource_id = headers[MSG_HEADER_RESOURCE_ID] else: if resource_id_required: raise Inconsistent('%s(%s) has been denied since the resource-id can not be found in the message headers' % (self._process_name, self._op)) self._resource_id = '' self._user_context_id = headers.get(MSG_HEADER_USER_CONTEXT_ID, None)
def _find_having_single(self, association_predicate, some_object): """ enforces exclusivity: 0 or 1 association allowed """ ret = self._find_having(association_predicate, some_object) if 1 < len(ret): raise Inconsistent( "More than one %s point to %s '%s'" % (association_predicate, self.iontype, some_object)) return ret
def read_attachment(self, attachment_id=''): attachment = self.read(attachment_id) if not isinstance(attachment, Attachment): raise Inconsistent("Object in datastore must be Attachment, not %s" % type(attachment)) if attachment.attachment_type == AttachmentType.BLOB: if type(attachment.content) is not str: raise BadRequest("Attachment content must be str") attachment.content = base64.decodestring(attachment.content) return attachment
def get_association(self, subject="", predicate="", object="", assoc_type=None, id_only=False): if predicate: assoc_type = assoc_type or AT.H2H assoc = self.rr_store.find_associations(subject, predicate, object, assoc_type, id_only=id_only) if not assoc: raise NotFound("Association for subject/predicate/object/type %s/%s/%s/%s not found" % ( str(subject),str(predicate),str(object),str(assoc_type))) elif len(assoc) > 1: raise Inconsistent("Duplicate associations found for subject/predicate/object/type %s/%s/%s/%s" % ( str(subject),str(predicate),str(object),str(assoc_type))) return assoc[0]
def create_resources_snapshot(self, persist=False, filename=None): ds = CouchDataStore(DataStore.DS_RESOURCES, profile=DataStore.DS_PROFILE.RESOURCES, config=CFG, scope=self.sysname) all_objs = ds.find_docs_by_view("_all_docs", None, id_only=False) log.info("Found %s objects in datastore resources", len(all_objs)) resources = {} associations = {} snapshot = dict(resources=resources, associations=associations) for obj_id, key, obj in all_objs: if obj_id.startswith("_design"): continue if not isinstance(obj, dict): raise Inconsistent("Object of bad type found: %s" % type(obj)) obj_type = obj.get("type_", None) if obj_type == "Association": associations[obj_id] = obj.get("ts", None) elif obj_type: resources[obj_id] = obj.get("ts_updated", None) else: raise Inconsistent("Object with no type_ found: %s" % obj) if persist: dtstr = datetime.datetime.today().strftime('%Y%m%d_%H%M%S') path = filename or "interface/rrsnapshot_%s.json" % dtstr snapshot_json = json.dumps(snapshot) with open(path, "w") as f: #yaml.dump(snapshot, f, default_flow_style=False) f.write(snapshot_json) log.debug( "Created resource registry snapshot. %s resources, %s associations", len(resources), len(associations)) return snapshot
def update_negotiation(self, sap=None, reason=None): #Find the Negotiation resource associated with this proposal if sap is None or sap.negotiation_id == '': raise Inconsistent('The Service Agreement Proposal must have a negotiation resource id associated with it') neg_obj = self.service_provider.clients.resource_registry.read(sap.negotiation_id) if sap.sequence_num != len(neg_obj.proposals): raise Inconsistent('The Service Agreement Proposal does not have the correct sequence_num value (%d) for this negotiation (%d)' % (sap.sequence_num, len(neg_obj.proposals))) #Synchronize negotiation status based on proposals if sap.proposal_status == ProposalStatusEnum.REJECTED: neg_obj.negotiation_status = NegotiationStatusEnum.REJECTED elif sap.proposal_status == ProposalStatusEnum.ACCEPTED: #Look for an previously Accepted proposal from the other party for prop in neg_obj.proposals: if prop.proposal_status == ProposalStatusEnum.ACCEPTED and prop.originator != sap.originator: neg_obj.negotiation_status = NegotiationStatusEnum.ACCEPTED if reason is not None: neg_obj.reason = reason #Add the current proposal to the Negotiation object to keep a record of it - then save it neg_obj.proposals.append(sap) neg_id,_ = self.service_provider.clients.resource_registry.update(neg_obj) self._publish_status_event(neg_obj) if neg_obj.negotiation_status == NegotiationStatusEnum.ACCEPTED: self._execute_accept_action(neg_obj.proposals[-1]) #Publish request granted notification self._publish_status_event(neg_obj, ProposalStatusEnum.GRANTED) return neg_id
def find_actor_identity_by_name(self, name=''): """Return the ActorIdentity object whose name attribute matches the passed value. @param name str @retval user_info ActorIdentity @throws NotFound failed to find ActorIdentity @throws Inconsistent Multiple ActorIdentity objects matched name """ objects, matches = self.clients.resource_registry.find_resources(RT.ActorIdentity, None, name, id_only=False) if not objects: raise NotFound("ActorIdentity with name %s does not exist" % name) if len(objects) > 1: raise Inconsistent("Multiple ActorIdentity objects with name %s exist" % name) return objects[0]
def _find_stemming_single(self, primary_object_id, association_predicate, some_object_type): """ enforces exclusivity: 0 or 1 association allowed """ ret = self._find_stemming(primary_object_id, association_predicate, some_object_type) if 1 < len(ret): raise Inconsistent("%s '%s' has more than one %s:" % (self.iontype, primary_object_id, association_predicate, some_object_type)) return ret
def create_extended_resource_container_list(self, extended_resource_type, resource_id_list, computed_resource_type=None, ext_associations=None, ext_exclude=None, **kwargs): """ Returns a list of extended resource containers for given list of resource_ids. """ if not isinstance(resource_id_list, types.ListType): raise Inconsistent("The parameter resource_id_list is not a list of resource_ids") ret = list() for res_id in resource_id_list: ext_res = self.create_extended_resource_container(extended_resource_type, res_id, computed_resource_type, ext_associations, ext_exclude ) ret.append(ext_res) return ret
def find_object(self, subject, predicate, object_type, id_only=False): subject_id, subject_type = self._extract_id_and_type(subject) objs, _ = self.RR.find_objects(subject=subject_id, predicate=predicate, object_type=object_type, id_only=id_only) if 1 == len(objs): return objs[0] elif 1 < len(objs): raise Inconsistent( "Expected 1 %s as object of %s '%s', got %d" % (object_type, subject_type, str(subject_id), len(objs))) else: raise NotFound("Expected 1 %s as object of %s '%s'" % (object_type, subject_type, str(subject_id)))
def _link_resources_single_subject(self, subject_id='', association_type='', object_id='', raise_exn=True): """ create an association where only one subject at a time can exist if there is an existing association, the choice is left to the user whether to raise exception or quietly remove/replace the existing one. @param subject_id the resource ID of the predefined type @param association_type the predicate @param object_id the resource ID of the type to be joined @param raise_exn whether a BadRequest error should be raised if a duplicate is attempted @todo check for errors: does RR check for bogus ids? """ # see if there are any other objects of this type and pred on this subject obj_type = self._get_resource_type_by_id(object_id) existing_links = self._find_having(association_type, object_id) if len(existing_links) > 1: raise Inconsistent( "Multiple %s-%s subjects found on the same %s object with id='%s'" % (self.iontype, association_type, obj_type, object_id)) if len(existing_links) > 0: if self._resource_link_exists(subject_id, association_type, object_id): log.debug( "Create %s Association (single subject) from '%s': ALREADY EXISTS" % (self._assn_name(association_type), self._toplevel_call())) return None if raise_exn: raise BadRequest( "Attempted to add a duplicate %s-%s association on a %s object with id='%s'" % (self.iontype, association_type, obj_type, subject_id)) self._unlink_resources(self, subject_id, association_type, existing_links[0]) return self._link_resources_lowlevel(subject_id, association_type, object_id, False)
def _read_by_path(self, path, orgname=None): """ Given a qualified path, find entry in directory and return DirEntry document or None if not found """ if path is None: raise BadRequest("Illegal arguments") orgname = orgname or self.orgname parent, key = path.rsplit("/", 1) parent = parent or "/" find_key = [orgname, key, parent] view_res = self.datastore.find_docs_by_view('directory', 'by_key', key=find_key, id_only=True) if len(view_res) > 1: raise Inconsistent("More than one directory entry found for key %s" % path) elif view_res: return view_res[0][2] # First value return None
def read_attachment(self, attachment_id='', include_content=False): """ Returns the metadata of an attachment. Unless indicated otherwise the content returned is only a name to the actual attachment content. """ attachment = self.read(attachment_id) if not isinstance(attachment, Attachment): raise Inconsistent( "Object in datastore must be Attachment, not %s" % type(attachment)) if include_content: attachment.content = self.rr_store.read_attachment( attachment_id, attachment_name=self.DEFAULT_ATTACHMENT_NAME) if attachment.attachment_type == AttachmentType.BLOB: if type(attachment.content) is not str: raise BadRequest("Attachment content must be str") return attachment