def parse_attachment(r, request): message = request.body # i need boundary to be in the message for email to parse it right if 'boundary' not in message[:message.index("--")]: if 'boundary' in request.META['CONTENT_TYPE']: message = request.META['CONTENT_TYPE'] + message else: raise BadRequest("Could not find the boundary for the multipart content") msg = email.message_from_string(message) if msg.is_multipart(): parts = [] for part in msg.walk(): parts.append(part) if len(parts) < 1: raise ParamError("The content of the multipart request didn't contain a statement") # ignore parts[0], it's the whole thing # parts[1] better be the statement r['body'] = convert_to_dict(parts[1].get_payload()) if len(parts) > 2: r['payload_sha2s'] = [] for a in parts[2:]: # attachments thehash = a.get("X-Experience-API-Hash") if not thehash: raise BadRequest("X-Experience-API-Hash header was missing from attachment") headers = defaultdict(str) r['payload_sha2s'].append(thehash) # Save msg object to cache att_cache.set(thehash, a) else: raise ParamError("This content was not multipart for the multipart request.") # see if the posted statements have attachments att_stmts = [] if isinstance(r['body'], list): for s in r['body']: if 'attachments' in s: att_stmts.append(s) elif 'attachments' in r['body']: att_stmts.append(r['body']) if att_stmts: # find if any of those statements with attachments have a signed statement signed_stmts = [(s,a) for s in att_stmts for a in s.get('attachments', None) if a['usageType'] == "http://adlnet.gov/expapi/attachments/signature"] for ss in signed_stmts: attmnt = att_cache.get(ss[1]['sha2']).get_payload(decode=True) jws = JWS(jws=attmnt) try: if not jws.verify() or not jws.validate(ss[0]): raise BadRequest("The JSON Web Signature is not valid") except JWSException as jwsx: raise BadRequest(jwsx)
def statements_post(req_dict): if req_dict['params'].keys(): raise ParamError("The post statements request contained unexpected parameters: %s" % ", ".join(req_dict['params'].keys())) payload_sha2s = req_dict.get('payload_sha2s', None) if isinstance(req_dict['body'], basestring): req_dict['body'] = convert_to_dict(req_dict['body']) try: validator = StatementValidator.StatementValidator(req_dict['body']) msg = validator.validate() except Exception, e: raise BadRequest(e.message)
def statements_put(req_dict): # Find any unexpected parameters rogueparams = set(req_dict['params']) - set(["statementId"]) if rogueparams: raise ParamError("The put statements request contained unexpected parameters: %s" % ", ".join(rogueparams)) # Statement id can must be supplied in query param. If in the body too, it must be the same if not 'statementId' in req_dict['params']: raise ParamError("Error -- statements - method = %s, but no statementId parameter or ID given in statement" % req_dict['method']) else: statement_id = req_dict['params']['statementId'] # Convert data so it can be parsed if isinstance(req_dict['body'], basestring): req_dict['body'] = convert_to_dict(req_dict['body']) # Try to get id if in body try: statement_body_id = req_dict['body']['id'] except Exception, e: statement_body_id = None
def parse_body(r, request): if request.method == 'POST' or request.method == 'PUT': # Parse out profiles/states if the POST dict is not empty if 'multipart/form-data' in request.META['CONTENT_TYPE']: if request.POST.dict().keys(): r['params'].update(request.POST.dict()) parser = MultiPartParser(request.META, StringIO.StringIO(request.raw_post_data),request.upload_handlers) post, files = parser.parse() r['files'] = files # If it is multipart/mixed, parse out all data elif 'multipart/mixed' in request.META['CONTENT_TYPE']: parse_attachment(r, request) # Normal POST/PUT data else: if request.body: # profile uses the request body r['raw_body'] = request.body # Body will be some type of string, not necessarily JSON r['body'] = convert_to_dict(request.body) else: raise BadRequest("No body in request") return r
def complex_get(param_dict, limit, language, format, attachments): # Tests if value is True or "true" vq = Q(voided=False) # keep track if a filter other than time or sequence is used reffilter = False sinceq = Q() if "since" in param_dict: sinceq = Q(stored__gt=convert_to_utc(param_dict["since"])) untilq = Q() if "until" in param_dict: untilq = Q(stored__lte=convert_to_utc(param_dict["until"])) # For statements/read/mine oauth scope authq = Q() if "auth" in param_dict and (param_dict["auth"] and "statements_mine_only" in param_dict["auth"]): authq = Q(authority=param_dict["auth"]["id"]) agentQ = Q() if "agent" in param_dict: reffilter = True agent = None data = param_dict["agent"] related = "related_agents" in param_dict and param_dict["related_agents"] if not type(data) is dict: data = convert_to_dict(data) try: agent = AgentManager(data).Agent if agent.objectType == "Group": groups = [] else: groups = agent.member.all() agentQ = Q(actor=agent) for g in groups: agentQ = agentQ | Q(actor=g) if related: me = chain([agent], groups) for a in me: agentQ = ( agentQ | Q(object_agent=a) | Q(authority=a) | Q(context_instructor=a) | Q(context_team=a) | Q(object_substatement__actor=a) | Q(object_substatement__object_agent=a) | Q(object_substatement__context_instructor=a) | Q(object_substatement__context_team=a) ) except IDNotFoundError: return [] verbQ = Q() if "verb" in param_dict: reffilter = True verbQ = Q(verb__verb_id=param_dict["verb"]) # activity activityQ = Q() if "activity" in param_dict: reffilter = True activityQ = Q(object_activity__activity_id=param_dict["activity"]) if "related_activities" in param_dict and param_dict["related_activities"]: activityQ = ( activityQ | Q(statementcontextactivity__context_activity__activity_id=param_dict["activity"]) | Q(object_substatement__object_activity__activity_id=param_dict["activity"]) | Q( object_substatement__substatementcontextactivity__context_activity__activity_id=param_dict[ "activity" ] ) ) registrationQ = Q() if "registration" in param_dict: reffilter = True registrationQ = Q(context_registration=param_dict["registration"]) # If want ordered by ascending stored_param = "-stored" if "ascending" in param_dict and param_dict["ascending"]: stored_param = "stored" stmtset = Statement.objects.filter(vq & untilq & sinceq & authq & agentQ & verbQ & activityQ & registrationQ) # only find references when a filter other than # since, until, or limit was used if reffilter: stmtset = findstmtrefs(stmtset.distinct(), sinceq, untilq) # Calculate limit of stmts to return return_limit = set_limit(limit) # If there are more stmts than the limit, need to break it up and return more id if stmtset.count() > return_limit: return initial_cache_return(stmtset, stored_param, return_limit, language, format, attachments) else: return create_stmt_result(stmtset, stored_param, language, format)