def get_profile_ids(self, activityId, since=None): ids = [] #make sure activityId exists try: # Always want global version activity = models.activity.objects.get(activity_id=activityId, global_representation=True) except models.activity.DoesNotExist: err_msg = 'There is no activity associated with the id: %s' % activityId log_message(self.log_dict, err_msg, __name__, self.get_profile_ids.__name__, True) update_parent_log_status(self.log_dict, 404) raise IDNotFoundError(err_msg) #If there is a since param return all profileIds since then if since: try: # this expects iso6801 date/time format "2013-02-15T12:00:00+00:00" profs = models.activity_profile.objects.filter(updated__gte=since, activity=activity) except ValidationError: from django.utils import timezone since_i = int(float(since))# this handles timestamp like str(time.time()) since_dt = datetime.datetime.fromtimestamp(since_i).replace(tzinfo=timezone.get_default_timezone()) profs = models.activity_profile.objects.filter(updated__gte=since_dt, activity=activity) ids = [p.profileId for p in profs] else: #Return all IDs of profiles associated with this activity b/c there is no since param ids = models.activity_profile.objects.filter(activity=activity).values_list('profileId', flat=True) return ids
def populateResult(self, stmt_data): log_message(self.log_dict, "Populating result", __name__, self.populateResult.__name__) resultExts = {} #Catch contradictory results if 'extensions' in stmt_data['result']: result = dict((key, value) for (key, value) in stmt_data['result'].items() if not key == 'extensions') resultExts = stmt_data['result']['extensions'] else: result = stmt_data['result'] # Validate duration, throw error if duration is not formatted correctly if 'duration' in result: try: dur = parse_duration(result['duration']) except ISO8601Error as e: log_message(self.log_dict, e.message, __name__, self.populateResult.__name__, True) update_parent_log_status(self.log_dict, 400) raise exceptions.ParamError(e.message) if 'score' in result.keys(): result['score'] = self.validateScoreResult(result['score']) result['score'] = self.saveScoreToDB(result['score']) #Save result return self.saveResultToDB(result, resultExts)
def get_profile_ids(self, profileId, activityId, since=None): ids = [] #make sure activityId exists try: activity = models.activity.objects.get(activity_id=activityId) except models.activity.DoesNotExist: err_msg = 'There is no activity associated with the id: %s' % activityId log_message(self.log_dict, err_msg, __name__, self.get_profile_ids.__name__, True) update_parent_log_status(self.log_dict, 404) raise IDNotFoundError(err_msg) #If there is a since param return all profileIds since then if since: try: profs = models.activity_profile.objects.filter(updated__gte=since, profileId=profileId, activity=activity) except ValidationError: since_i = int(float(since)) since_dt = datetime.datetime.fromtimestamp(since_i) profs = models.activity_profile_set.filter(update__gte=since_dt, profileId=profileId, activity=activity) ids = [p.profileId for p in profs] else: #Return all IDs of profiles associated with this activity b/c there is no since param ids = models.activity_profile.objects.filter(activity=activity).values_list('profileId', flat=True) return ids
def activity_profile_get(req_dict): log_dict = req_dict['initial_user_action'] log_info_processing(log_dict, 'GET', __name__) #TODO:need eTag for returning list of IDs? # Instantiate ActivityProfile ap = ActivityProfile.ActivityProfile(log_dict=log_dict) # Get profileId and activityId profileId = req_dict.get('profileId', None) activityId = req_dict.get('activityId', None) #If the profileId exists, get the profile and return it in the response if profileId: resource = ap.get_profile(profileId, activityId) response = HttpResponse(resource.profile.read(), content_type=resource.content_type) response['ETag'] = '"%s"' % resource.etag update_parent_log_status(log_dict, 200) return response #Return IDs of profiles stored since profileId was not submitted since = req_dict.get('since', None) resource = ap.get_profile_ids(since, activityId) response = HttpResponse(json.dumps([k for k in resource]), content_type="application/json") response['since'] = since #response['ETag'] = '"%s"' % resource.etag update_parent_log_status(log_dict, 200) return response
def statements_post(req_dict): stmt_responses = [] log_dict = req_dict['initial_user_action'] log_info_processing(log_dict, 'POST', __name__) define = True if 'oauth_define' in req_dict: define = req_dict['oauth_define'] # Handle batch POST if type(req_dict['body']) is list: try: for st in req_dict['body']: stmt = Statement.Statement(st, auth=req_dict['auth'], log_dict=log_dict, define=define).model_object stmt_responses.append(str(stmt.statement_id)) except Exception, e: for stmt_id in stmt_responses: try: models.statement.objects.get(statement_id=stmt_id).delete() except models.statement.DoesNotExist: pass # stmt already deleted log_exception(log_dict, e.message, statements_post.__name__) update_parent_log_status(log_dict, 500) raise e
def statements_get(req_dict): log_dict = req_dict['initial_user_action'] log_info_processing(log_dict, 'GET', __name__) if 'statements_mine_only' in req_dict: mine_only = True else: mine_only = False stmt_result = {} # If statementId is in req_dict then it is a single get if 'statementId' in req_dict: statementId = req_dict['statementId'] # Try to retrieve stmt, if DNE then return empty else return stmt info try: st = models.statement.objects.get(statement_id=statementId) except models.statement.DoesNotExist: err_msg = 'There is no statement associated with the id: %s' % statementId log_exception(log_dict, err_msg, statements_get.__name__) update_parent_log_status(log_dict, 404) raise exceptions.IDNotFoundError(err_msg) # check if stmt authority is in oauth group if mine_only and not (st.authority.id == req_dict['auth'].id): raise exceptions.Forbidden("Incorrect permissions to view statements that do not have auth %s" % str(req_dict['auth'])) stmt_result = st.object_return() else: stmt_list = retrieve_statement.complex_get(req_dict) stmt_result = retrieve_statement.build_statement_result(req_dict, stmt_list) update_parent_log_status(log_dict, 200) return HttpResponse(stream_response_generator(stmt_result), mimetype="application/json", status=200)
def __init__(self, initial=None, create=False, log_dict=None): self.initial = initial self.log_dict = log_dict params = self.initial if isinstance(params, dict): self.initial = json.dumps(self.initial) else: try: params = ast.literal_eval(params) except: params = json.loads(params) if 'objectType' in params and params['objectType'] == 'Group': obj = group else: obj = agent if create: self.agent, created = obj.objects.gen(**params) if created: log_message(self.log_dict, "Created %s in database" % self.agent.objectType, __name__, self.__init__.__name__) elif not created: log_message(self.log_dict, "Retrieved %s from database" % self.agent.objectType, __name__, self.__init__.__name__) else: try: if 'member' in params: params.pop('member', None) self.agent = obj.objects.get(**params) log_message(self.log_dict, "Retrieved %s from database" % self.agent.objectType, __name__, self.__init__.__name__) except: err_msg = "Error with Agent. The agent partial (%s) did not match any agents on record" % self.initial log_message(self.log_dict, err_msg, __name__, self.__init__.__name__, True) update_parent_log_status(self.log_dict, 404) raise IDNotFoundError(err_msg)
def voidStatement(self,stmt_id): str_id = str(stmt_id) log_message(self.log_dict, "Voiding Statement with ID %s" % str_id, __name__, self.voidStatement.__name__) # Retrieve statement, check if the verb is 'voided' - if not then set the voided flag to true else return error # since you cannot unvoid a statement and should just reissue the statement under a new ID. try: stmt = models.statement.objects.get(statement_id=stmt_id) except Exception: err_msg = "Statement with ID %s does not exist" % str(stmt_id) log_message(self.log_dict, err_msg, __name__, self.voidStatement.__name__, True) update_parent_log_status(self.log_dict, 404) raise exceptions.IDNotFoundError(err_msg) # Check if it is already voided if not stmt.voided: stmt.voided = True stmt.save() # Create statement ref stmt_ref = models.StatementRef(ref_id=stmt_id) stmt_ref.save() return stmt_ref else: err_msg = "Statement with ID: %s is already voided, cannot unvoid. Please re-issue the statement under a new ID." % str_id log_message(self.log_dict, err_msg, __name__, self.voidStatement.__name__, True) update_parent_log_status(self.log_dict, 403) raise exceptions.Forbidden(err_msg)
def populateResult(self, stmt_data, verb): log_message(self.log_dict, "Populating result", __name__, self.populateResult.__name__) resultExts = {} #Catch contradictory results if 'extensions' in stmt_data['result']: result = {key: value for key, value in stmt_data['result'].items() if not key == 'extensions'} resultExts = stmt_data['result']['extensions'] else: result = stmt_data['result'] self.validateVerbResult(result, verb, stmt_data['object']) # Validate duration, throw error if duration is not formatted correctly if 'duration' in result: try: dur = parse_duration(result['duration']) except ISO8601Error as e: log_message(self.log_dict, e.message, __name__, self.populateResult.__name__, True) update_parent_log_status(self.log_dict, 400) raise exceptions.ParamError(e.message) #Once found that the results are valid against the verb, check score object and save if 'score' in result.keys(): result['score'] = self.validateScoreResult(result['score']) result['score'] = self.saveScoreToDB(result['score']) #Save result return self.saveResultToDB(result, resultExts)
def get_profile(self, profileId): try: return self.agent.agent_profile_set.get(profileId=profileId) except: err_msg = 'There is no profile associated with the id: %s' % profileId log_message(self.log_dict, err_msg, __name__, self.get_profile.__name__, True) update_parent_log_status(self.log_dict, 404) raise IDNotFoundError(err_msg)
def parse(self,data): try: params = json.loads(data) except Exception, e: err_msg = "Error parsing the Statement object. Expecting json. Received: %s which is %s" % (data, type(data)) log_message(self.log_dict, err_msg, __name__, self.parse.__name__, True) update_parent_log_status(self.log_dict, 400) raise exceptions.ParamError(err_msg)
def validate_incoming_uuid(self, incoming_uuid): regex = re.compile("[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}") match = regex.match(incoming_uuid) if not match: err_msg = "%s is not a valid UUID" % incoming_uuid log_message(self.log_dict, err_msg, __name__, self.validate_incoming_uuid.__name__, True) update_parent_log_status(self.log_dict, 400) raise exceptions.ParamError(err_msg)
def agents_get(req_dict): log_dict = req_dict['initial_user_action'] log_info_processing(log_dict, 'GET', __name__) agent = req_dict['agent'] a = Agent.Agent(agent,log_dict=log_dict) resp = HttpResponse(a.get_person_json(), mimetype="application/json") update_parent_log_status(log_dict, 200) return resp
def activity_state_delete(req_dict): log_dict = req_dict['initial_user_action'] log_info_processing(log_dict, 'DELETE', __name__) actstate = ActivityState.ActivityState(req_dict, log_dict=log_dict) # Delete state actstate.delete(req_dict['auth']) update_parent_log_status(log_dict, 204) return HttpResponse('', status=204)
def statements_put(req_dict): log_dict = req_dict['initial_user_action'] log_info_processing(log_dict, 'PUT', __name__) # Set statement ID in body so all data is together req_dict['body']['statement_id'] = req_dict['statementId'] stmt = Statement.Statement(req_dict['body'], auth=req_dict['auth'], log_dict=log_dict).model_object update_parent_log_status(log_dict, 204) return HttpResponse("No Content", status=204)
def activity_state_put(req_dict): log_dict = req_dict['initial_user_action'] log_info_processing(log_dict, 'PUT', __name__) # test ETag for concurrency actstate = ActivityState.ActivityState(req_dict, log_dict=log_dict) actstate.put() update_parent_log_status(log_dict, 204) return HttpResponse("", status=204)
def populate_extensions(self, act_def): for k, v in act_def['extensions'].items(): if not uri.validate_uri(k): err_msg = "Extension ID %s is not a valid URI" % k log_message(self.log_dict, err_msg, __name__, self.populate_extensions.__name__, True) update_parent_log_status(self.log_dict, 400) raise exceptions.ParamError(err_msg) act_def_ext = models.extensions(key=k, value=v, content_object=self.activity.activity_definition) act_def_ext.save()
def get(self, auth): agent = self.__get_agent() try: if self.registrationId: return models.activity_state.objects.get(state_id=self.stateId, agent=agent, activity=self.activity, registration_id=self.registrationId) return models.activity_state.objects.get(state_id=self.stateId, agent=agent, activity=self.activity) except models.activity_state.DoesNotExist: err_msg = 'There is no activity state associated with the id: %s' % self.stateId log_message(self.log_dict, err_msg, __name__, self.get.__name__, True) update_parent_log_status(self.log_dict, 404) raise IDNotFoundError(err_msg)
def get_ids(self, auth): try: state_set = self.get_set(auth) except models.activity_state.DoesNotExist: err_msg = 'There is no activity state associated with the ID: %s' % self.stateId log_message(self.log_dict, err_msg, __name__, self.get_ids.__name__, True) update_parent_log_status(self.log_dict, 404) raise IDNotFoundError(err_msg) if self.since: state_set = state_set.filter(updated__gte=self.since) return state_set.values_list('state_id', flat=True)
def agent_profile_put(req_dict): log_dict = req_dict['initial_user_action'] log_info_processing(log_dict, 'PUT', __name__) # test ETag for concurrency agent = req_dict['agent'] a = Agent.Agent(agent, create=True, log_dict=log_dict) a.put_profile(req_dict) update_parent_log_status(log_dict, 204) return HttpResponse("", status=204)
def agent_profile_delete(req_dict): log_dict = req_dict['initial_user_action'] log_info_processing(log_dict, 'DELETE', __name__) agent = req_dict['agent'] a = Agent.Agent(agent, log_dict=log_dict) profileId = req_dict['profileId'] a.delete_profile(profileId) update_parent_log_status(log_dict, 204) return HttpResponse('', status=204)
def activity_profile_delete(req_dict): log_dict = req_dict['initial_user_action'] log_info_processing(log_dict, 'DELETE', __name__) #Instantiate activity profile ap = ActivityProfile.ActivityProfile(log_dict=log_dict) # Delete profile and return success ap.delete_profile(req_dict) update_parent_log_status(log_dict, 200) return HttpResponse('Success -- activity profile - method = DELETE - profileId = %s' % req_dict['profileId'], status=200)
def activity_profile_put(req_dict): log_dict = req_dict['initial_user_action'] log_info_processing(log_dict, 'PUT', __name__) #Instantiate ActivityProfile ap = ActivityProfile.ActivityProfile(log_dict=log_dict) #Put profile and return 204 response ap.put_profile(req_dict) update_parent_log_status(log_dict, 200) return HttpResponse('Success -- activity profile - method = PUT - profileId = %s' % req_dict['profileId'], status=200)
def put_profile(self, request_dict): #Parse out profile from request_dict try: profile = ContentFile(request_dict['profile'].read()) except: try: profile = ContentFile(request_dict['profile']) except: profile = ContentFile(str(request_dict['profile'])) #Check if activity exists try: # Always want global version activity = models.activity.objects.get(activity_id=request_dict['activityId'], global_representation=True) except models.activity.DoesNotExist: err_msg = 'There is no activity associated with the id: %s' % request_dict['activityId'] log_message(self.log_dict, err_msg, __name__, self.put_profile.__name__, True) update_parent_log_status(self.log_dict, 404) raise IDNotFoundError(err_msg) user = get_user_from_auth(request_dict.get('auth', None)) #Get the profile, or if not already created, create one p,created = models.activity_profile.objects.get_or_create(profileId=request_dict['profileId'],activity=activity, user=user) if created: log_message(self.log_dict, "Created Activity Profile", __name__, self.put_profile.__name__) else: #If it already exists delete it etag.check_preconditions(request_dict,p, required=True) p.profile.delete() log_message(self.log_dict, "Retrieved Activity Profile", __name__, self.put_profile.__name__) #Save profile content type based on incoming content type header and create etag p.content_type = request_dict['CONTENT_TYPE'] p.etag = etag.create_tag(profile.read()) #Set updated if request_dict['updated']: p.updated = request_dict['updated'] #Go to beginning of file profile.seek(0) #If it didn't exist, save it if created: p.save() #Set filename with the activityID and profileID and save fn = "%s_%s" % (p.activity_id,request_dict.get('filename', p.id)) p.profile.save(fn, profile) log_message(self.log_dict, "Saved Activity Profile", __name__, self.put_profile.__name__)
def validateVerbResult(self,result, verb, obj_data): completedVerbs = ['completed', 'mastered', 'passed', 'failed'] #If completion is false then verb cannot be completed, mastered, if 'completion' in result: if result['completion'] == False: if verb in completedVerbs: err_msg = "Completion must be True if using the verb %s" % verb log_message(self.log_dict, err_msg, __name__, self.validateVerbResult.__name__, True) #Throw exceptions b/c those verbs must have true completion update_parent_log_status(self.log_dict, 400) raise exceptions.ParamError(err_msg) if verb == 'mastered' and result['success'] == False: err_msg = "Result success must be True if verb is %s" % verb log_message(self.log_dict, err_msg, __name__, self.validateVerbResult.__name__, True) #Throw exception b/c mastered and success contradict each other or completion is false update_parent_log_status(self.log_dict, 400) raise exceptions.ParamError(err_msg) if verb == 'passed' and result['success'] == False: err_msg = "Result success must be True if verb is %s" % verb log_message(self.log_dict, err_msg, __name__, self.validateVerbResult.__name__, True) #Throw exception b/c passed and success contradict each other or completion is false update_parent_log_status(self.log_dict, 400) raise exceptions.ParamError(err_msg) if verb == 'failed' and result['success'] == True: err_msg = "Result success must be False if verb is %s" % verb log_message(self.log_dict, err_msg, __name__, self.validateVerbResult.__name__, True) #Throw exception b/c failed and success contradict each other or completion is false update_parent_log_status(self.log_dict, 400) raise exceptions.ParamError(err_msg)
def __init__(self, initial=None, create=False, log_dict=None, define=True): self.initial = initial self.log_dict = log_dict self.define = define params = self.initial if not isinstance(params, dict): try: params = json.loads(self.initial) except Exception, e: err_msg = "Error parsing the Agent object. Expecting json. Received: %s which is %s" % (self.initial, type(self.initial)) log_message(self.log_dict, err_msg, __name__, self.__init__.__name__, True) update_parent_log_status(self.log_dict, 400) raise exceptions.ParamError(err_msg)
def get(self, auth): agent = self.__get_agent() # if not agent.mbox is None: # if agent.mbox != auth.email: # raise Forbidden("Unauthorized to retrieve activity state with ID %s" % self.stateId) try: if self.registrationId: return models.activity_state.objects.get(state_id=self.stateId, agent=agent, activity=self.activity, registration_id=self.registrationId) return models.activity_state.objects.get(state_id=self.stateId, agent=agent, activity=self.activity) except models.activity_state.DoesNotExist: err_msg = 'There is no activity state associated with the id: %s' % self.stateId log_message(self.log_dict, err_msg, __name__, self.get.__name__, True) update_parent_log_status(self.log_dict, 404) raise IDNotFoundError(err_msg)
def __init__(self, data, auth, log_dict=None): self.log_dict = log_dict unallowed_fields = ['id', 'stored', 'authority'] # Raise error if an unallowed field is present for field in unallowed_fields: if field in data: update_parent_log_status(self.log_dict, 400) raise exceptions.ParamError("%s is not allowed in a SubStatement.") # Make sure object isn't another substatement if 'objectType' in data['object']: if data['object']['objectType'].lower() == 'substatement': update_parent_log_status(self.log_dict, 400) raise exceptions.ParamError("SubStatements cannot be nested inside of other SubStatements") Statement.__init__(self, data, auth)
def activity_state_get(req_dict): log_dict = req_dict['initial_user_action'] log_info_processing(log_dict, 'GET', __name__) # add ETag for concurrency actstate = ActivityState.ActivityState(req_dict, log_dict=log_dict) stateId = req_dict.get('stateId', None) if stateId: # state id means we want only 1 item resource = actstate.get(req_dict['auth']) response = HttpResponse(resource.state.read()) response['ETag'] = '"%s"' %resource.etag else: # no state id means we want an array of state ids resource = actstate.get_ids(req_dict['auth']) response = HttpResponse(json.dumps([k for k in resource]), content_type="application/json") update_parent_log_status(log_dict, 200) return response
def saveContextToDB(self, context, contextExts): # Set context activities to context dict con_act_data = None if 'contextActivities' in context: con_act_data = context['contextActivities'] del context['contextActivities'] # Set context statement cs = None if 'cntx_statement' in context: cs = context['cntx_statement'] del context['cntx_statement'] # Save context cntx = models.context(content_object=self.model_object, **context) cntx.save() # Set context in context statement and save if cs: cs.context = cntx cs.save() # Save context activities if con_act_data: for con_act in con_act_data.items(): ca_id = con_act[1]['id'] if not uri.validate_uri(ca_id): raise exceptions.ParamError('Context Activity ID %s is not a valid URI' % ca_id) ca = models.ContextActivity(key=con_act[0], context_activity=ca_id, context=cntx) ca.save() cntx.save() # Save context extensions if contextExts: for k, v in contextExts.items(): if not uri.validate_uri(k): err_msg = "Extension ID %s is not a valid URI" % k log_message(self.log_dict, err_msg, __name__, self.saveContextToDB.__name__, True) update_parent_log_status(self.log_dict, 400) raise exceptions.ParamError(err_msg) conExt = models.extensions(key=k, value=v, content_object=cntx) conExt.save() log_message(self.log_dict, "Context saved to database", __name__, self.saveContextToDB.__name__) return cntx