def init_empty_target_mapping(self, exp_uid, n): """ Create a target doc that indicates a targetless experiment, the default state upon initialization. This doc is formatted as follows: {'targetless': True, 'exp_uid': exp_uid} Inputs: (string) exp_uid, (int) n Outputs: (dict) {} Usage: ::\n didSucceed = targetmapper.init_empty_target_mapping(exp_uid) """ # Initilize target document and insert into MongoDB doc = {'targetless': True, 'exp_uid': exp_uid} didSucceed, message = db.setDoc(self.database_id, self.bucket_id, None, doc) # If target doc could not be created, throw an error if not didSucceed: raise DatabaseException("Failed to init_empty_target_mapping: %s"%(message)) # Get all docs related to the specified exp_uid mongotized_target_blob,didSucceed,message = db.getDocsByPattern(self.database_id, self.bucket_id, {'exp_uid': exp_uid}) # If the newly initialized DB docs can't be found, throw an error if not didSucceed: raise DatabaseException("Failed to init_empty_target_mapping: %s"%(message)) # Pop target_dict out of list target_blob_dict = mongotized_target_blob.pop(0) # Return target_blob_dict of all targets corresponding to current exp_uid return {}
def get_targetID_given_index(self, exp_uid, index): """ Get the client supplied target_id given an internal NEXT target index Inputs: (string) exp_uid, (int) index Outputs: (string) target_id Usage: ::\n didSucceed = targetmapper.get_targetID_given_index(exp_uid, index) """ target_data,didSucceed,message = db.getDocsByPattern(self.database_id, self.bucket_id, {'exp_uid': exp_uid, 'targetless': True}) # Pass back message if getDocsByPattern fails if not didSucceed: raise DatabaseException("Failed to get_targetID_given_index: %s"%(message)) # This line is key. If no doc exists with the specified exp_uid and targetless = True, then targetless = False if not target_data: return index # Get an individual target form the DB given exp_uid and index got_target,didSucceed,message = db.getDocsByPattern(self.database_id, self.bucket_id, {'exp_uid': exp_uid, 'index': index}) # If doc cannot be retreived, throw an error if not didSucceed: raise DatabaseException("Failed to get_targetID_given_index: %s"%(message)) # I'm not sure if getDocsByPattern will return list if only 1 doc is retrevied. If this fails, remove this line. got_target = got_target.pop(0) # Get target_id out of target dictionary target_id = got_target['target_id'] return target_id
def get_target_data(self, exp_uid, index): """ Get an individual targets metadata given that targets index. Inputs: (string) exp_uid, index Outputs: (dict) target_data Usage: ::\n didSucceed = targetmapper.init_empty_target_mapping(exp_uid, n) """ target_data,didSucceed,message = db.getDocsByPattern(self.database_id, self.bucket_id, {'exp_uid': exp_uid, 'targetless': False}) # Pass back message if getDocsByPattern fails if not didSucceed: raise DatabaseException("Failed to get_target_data: %s"%(message)) # This line is key. If no doc exists with the specified exp_uid and targetless = True, then targetless = False if not target_data: return {'target_id':index, 'primary_description':index, 'primary_type':'text', 'alt_description':index, 'alt_type':'text'} # Get an individual target form the DB given exp_uid and index target_data,didSucceed,message = db.getDocsByPattern(self.database_id, self.bucket_id, {'exp_uid': exp_uid, 'index':index}) # If doc cannot be retreived, throw an error if not didSucceed: raise DatabaseException("Failed to get_target_data: %s"%(message)) # Pop target_dict out of list and return target_data_dict = target_data.pop(0) return target_data_dict
def get_exp_key(self, site_id, site_key, exp_uid): """ Get the key associated to an experiment. Verifies the site and that the experiment belongs to this site. Inputs: (string) site_id, (string) site_key, (string) exp_uid Outputs: (string) exp_key Usage: ::\n exp_key = keychain.get_exp_key(site_id, site_key, exp_uid) """ #Verify that these are proper credentials for this site if not self.verify_site_key(site_id, site_key): return "Invalid Credentials" # Verify that the experiment actually belongs to this site if not self.verify_site_exp_ownership(site_id, exp_uid): return "This experiment does not belong to this site or does not exist." docs, didSucceed, message = db.getDocsByPattern( self.database_id, self.bucket_id, {'object_id': exp_uid}) if not didSucceed: raise DatabaseException( "Failed to access database in the keychain. %s" % (message)) return docs[0]["_id"]
def create_perm_key(self, exp_uid, exp_key): """ Create a permanent key associated to an experiment for a widget. Verifies the experiment id and key. Inputs: (string) exp_uid, (string) exp_key Outputs: (string) perm_key Usage: ::\n perm_key = keychain.get_perm_key(exp_uid, exp_key) """ #Verify that these are proper credentials for this experiment if not self.verify_site_key(exp_uid, exp_key): return "Invalid Credentials" perm_key = '%030x' % random.randrange(16**30) doc = {'object_id': exp_uid, 'type': 'perm', 'duration': 0, 'tries': 0} didSucceed, message = db.setDoc(self.database_id, self.bucket_id, perm_key, doc) if not didSucceed: raise DatabaseException( "Failed to access database in the keychain. %s" % (message)) return perm_key
def get_perm_key(self, exp_uid, exp_key): """ Get a permanent key associated to an experiment for a widget. Verifies the experiment id and key. Inputs: (string) exp_uid, (string) exp_key Outputs: (string) perm_key Usage: ::\n perm_key = keychain.get_perm_key(exp_uid, exp_key) """ #Verify that these are proper credentials for this experiment if not self.verify_exp_key(exp_uid, exp_key): return "Invalid Credentials" docs, didSucceed, message = db.getDocsByPattern( self.database_id, self.bucket_id, { 'object_id': exp_uid, 'type': 'perm' }) if not didSucceed: raise DatabaseException( "Failed to access database in the keychain. %s" % (message)) return docs[0]["_id"]
def create_exp_key(self, site_id, site_key, exp_uid): """ Create an experiment key given a site_key. Verifies the site and that the experiment belongs to this site. Inputs: (string) site_id, (string) site_key, (string) exp_uid Outputs: (string) exp_key Usage: ::\n exp_key = keychain.create_exp_key(site_id, site_key, exp_uid) """ # Verify that these are proper credentials for this site if not self.verify_site_key(site_id, site_key): return "Invalid credentials" # Verify that the experiment actually belongs to this site if not self.verify_site_exp_ownership(site_id, exp_uid): return "This experiment does not belong to this site or does not exist." exp_key = '%030x' % random.randrange(16**30) doc = {'object_id': exp_uid, 'type': 'exp', 'duration': 0, 'tries': 0} didSucceed, message = db.setDoc(self.database_id, self.bucket_id, exp_key, doc) if not didSucceed: raise DatabaseException( "Failed to access database in the keychain. %s" % (message)) return exp_key
def get_target_mapping(self, exp_uid): """ Get the full target mapping. This be useful for pages that want to show/load the entire target set. Inputs: (string) exp_uid Outputs: (boolean) target_data Usage: ::\n didSucceed = targetmapper.init_empty_target_mapping(exp_uid, n) """ # Get all docs for specified exp_uid mongotized_target_blob,didSucceed,message = db.getDocsByPattern(self.database_id, self.bucket_id, {'exp_uid': exp_uid}) # If no docs with exp_uid can be retreived, throw an error if not didSucceed: raise DatabaseException("Failed to get_target_mapping: %s"%(message)) # Pop target_blob_dict out of list for i in range(len(mongotized_target_blob)): if 'targetless' in mongotized_target_blob[i].keys(): mongotized_target_blob.pop(i) break target_blob_dict = mongotized_target_blob return target_blob_dict
def get_exp_key(self, exp_uid): """ Get the key associated to an experiment. Inputs: (string) exp_uid Outputs: (string) exp_key Usage: ::\n exp_key = keychain.get_exp_key(exp_uid) """ docs, didSucceed, message = db.getDocsByPattern( self.database_id, self.bucket_id, {'object_id': exp_uid}) if not didSucceed: raise DatabaseException( "Failed to access database in the keychain. %s" % (message)) return docs[0]["_id"]
def create_exp_key(self, exp_uid): """ Create an experiment key given a site_key. Verifies the site and that the experiment belongs to this site. Inputs: (string) exp_uid Outputs: (string) exp_key Usage: ::\n exp_key = keychain.create_exp_key(exp_uid) """ exp_key = '%030x' % random.randrange(16**30) doc = {'object_id': exp_uid, 'type': 'exp', 'duration': 0, 'tries': 0} didSucceed, message = db.setDoc(self.database_id, self.bucket_id, exp_key, doc) if not didSucceed: raise DatabaseException( "Failed to access database in the keychain. %s" % (message)) return exp_key
def verify_exp_key(self, exp_uid, exp_key): """ Verify a key belongs to an experiment. Inputs: (string) exp_key, (string) exp_uid Outputs: (bool) Usage: ::\n if not verify_exp_key(exp_uid, exp_key): return "Invalid Credentials" """ value, didSucceed, message = db.get(self.database_id, self.bucket_id, exp_key, 'object_id') if not didSucceed: raise DatabaseException( "Failed to access database in the keychain. %s" % (message)) if value == exp_uid: return True return False
def verify_site_exp_ownership(self, site_id, exp_uid): """ Verify that a site owns an experiment. Inputs: (string) client_id, (string) site_id Outputs: (bool) Usage: ::\n keychain.verify_client_site_ownership(client_id, site_id) """ # Verify that the experiment actually belongs to this site value, didSucceed, message = db.get(self.database_id, "experiments", exp_uid, "site_id") if not didSucceed: raise DatabaseException( "Failed to access database in the keychain. %s" % (message)) if value == site_id: return True return False
def create_temp_keys(self, exp_uid, exp_key, n=1, tries=100, duration=60): """ Create temporary keys for widget access. Verifies the exp key and uid. A number of tires and a duration(minutes) can be specified. Inputs: (string) exp_uid, (string) exp_key, (int) tries (default 1), (int) duration (default 60) Outputs: (string) temp_key Usage: ::\n perm_key = keychain.get_temp_key(exp_uid, exp_key, tries=5, duration=10) """ #Verify that these are proper credentials for this experiment if not self.verify_site_key(exp_uid, exp_key): return "Invalid Credentials" temp_keys = [] for i in range(n): temp_key = '%030x' % random.randrange(16**30) doc = { 'object_id': exp_uid, 'type': 'temp', 'duration': duration, 'tries': 2 * tries } didSucceed, message = db.setDoc(self.database_id, self.bucket_id, temp_key, doc) temp_keys.append(temp_key) if not didSucceed: raise DatabaseException( "Failed to access database in the keychain. %s" % (message)) return temp_keys
def create_site_key(self, site_id): """ Create a site key. Inputs: (string) site_id Outputs: (string) site_key Usage: ::\n site_key = keychain.create_site_key(site_id) """ site_key = '%030x' % random.randrange(16**30) doc = {'object_id': site_id, 'type': 'site', 'duration': 0, 'tries': 0} didSucceed, message = db.setDoc(self.database_id, self.bucket_id, site_key, doc) if not didSucceed: raise DatabaseException( "Failed to access database in the keychain. %s" % (message)) return site_key
def verify_widget_key(self, exp_uid, key): """ Verify a widget key belongs to an experiment. If the key is permanent, it is just verified. If the key is temporary, the number of tries is decreased by 1, and the "access_time" is adjusted. If this causes the key to expire, the key is deleted from the database. Inputs: (string) key, (string) exp_uid Outputs: (bool) Usage: ::\n if not verify_exp_key(exp_uid, key): return "Invalid Credentials" """ doc, didSucceed, message = db.getDoc(self.database_id, self.bucket_id, key) print "keychain.py/verify_widget_key", doc if not didSucceed: raise DatabaseException( "Failed to access database in the keychain. %s" % (message)) hasTries = False hasTime = False print "tries", doc["tries"] if doc['object_id'] == exp_uid: if doc['type'] == 'perm': return True elif doc['type'] == 'temp': curr_time = time.time() if doc['tries'] > 0: hasTries = True if 'start_time' in doc.keys() and doc['duration'] > 0: if curr_time - doc[ 'last_access_time'] < 60000 * doc['duration']: hasTime = True else: hasTime = False elif doc['duration'] > 0: didSucceed, message = db.set(self.database_id, self.bucket_id, key, 'start_time', curr_time) if not didSucceed: raise DatabaseException( "Failed to access database in the keychain. %s" % (message)) hasTime = True # Update the key if we have tries and time left if hasTries and hasTime: if doc['tries'] <= 0: return False #db.delete(self.database_id, self.bucket_id, key) else: didSucceed, message = db.set(self.database_id, self.bucket_id, key, 'tries', doc['tries'] - 1) if not didSucceed: raise DatabaseException( "Failed to access database in the keychain. %s" % (message)) didSucceed, message = db.set(self.database_id, self.bucket_id, key, 'last_access_time', curr_time) if not didSucceed: raise DatabaseException( "Failed to access database in the keychain. %s" % (message)) return True # This key is stale. It should be deleted. else: #db.delete(self.database_id, self.bucket_id, key) return False return False
def create_target_mapping(self, exp_uid, target_blob): """ Update the default target docs in the DB if a user uploads a target set. Target_blob should be a list of targets, with each individual target having the following format. All feilds are REQUIRED. target_id: a unique target identifier init by the client index: the next_backend target object index primary_description (possibly image URI, or text) primary_type (img/text/audio/etc, tells how to display primary_description in widget) alternative_description (text descriptor, perhaps a caption for the image or subtitle for primary_description) features (list of floats, this will also be saved in the backend but its best to save this here as well I think. disk space is effectively infinite) Inputs: (string) exp_uid, (list) target_blob Outputs: (boolean) didSucceed Usage: ::\n didSucceed = targetmapper.create_target_mapping(exp_uid, target_blob) {'target_id': superhappy, 'index': 23, 'primary_description': s3.com/superhappy, 'primary_type': img, 'alt_description': a super happy person, 'features': features} """ #Verify that target_blob object has valid target mapping format #if not self.verify_target_map_format(exp_uid, target_blob): # print "Invalid TargetMap Format. Please check your target upload CSV file and include all of the required feilds." # return "Invalid TargetMap Format. Please check your target upload CSV file and include all of the required feilds." # Delete target doc indicating targetless initialization didSucceed,message = db.deleteDocsByPattern(self.database_id,self.bucket_id,{'exp_uid': exp_uid, 'targetless': True}) if not didSucceed: raise DatabaseException("Failed to create_target_mapping: %s"%(message)) # Recreate target document to denote target mapping has been created doc = {'targetless': False, 'exp_uid': exp_uid} didSucceed, message = db.setDoc(self.database_id, self.bucket_id, None, doc) if not didSucceed: raise DatabaseException("Failed to create_target_mapping: %s"%(message)) # Iteratively initilize target documents and insert into MongoDB for ii in range(len(target_blob)): # Parse target specific args out of target_blob at index ii target_tmp = target_blob[ii] target_id = target_tmp['target_id'] index = ii primary_description = target_tmp['primary_description'] primary_type = target_tmp['primary_type'] alt_type = target_tmp['alt_type'] alt_description = target_tmp['alt_description'] # Structure target document for MongoDB doc = {'index': index, 'target_id': target_id, 'primary_description': primary_description, 'primary_type': primary_type, 'alt_description': alt_description, 'alt_type': alt_type, 'exp_uid': exp_uid} didSucceed, message = db.setDoc(self.database_id, self.bucket_id, None, doc) # If target not successfully created, throw an error if not didSucceed: raise DatabaseException("Failed to create_target_mapping: %s"%(message)) # Get all docs related to the specified exp_uid mongotized_target_blob,didSucceed,message = db.getDocsByPattern(self.database_id, self.bucket_id, {'exp_uid': exp_uid}) # If the newly initialized DB docs can't be found, throw an error if not didSucceed: raise DatabaseException("Failed to create_target_mapping: %s"%(message)) # Pop target_dict out of list target_blob_dict = mongotized_target_blob.pop(0) # Return target_blob_dict of all targets corresponding to current exp_uid return target_blob_dict