def statements_put(req_dict): # Find any unexpected parameters rogueparams = set(req_dict['params']) - set(["statementId"]) if rogueparams and not ignore_rogue_params: 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 process_complex_get(req_dict): mime_type = "application/json" # Parse out params into single dict-GET data not in body param_dict = {} try: param_dict = req_dict['body'] if not isinstance(param_dict, dict): param_dict = convert_to_dict(param_dict) except KeyError: pass # no params in the body param_dict.update(req_dict['params']) format = param_dict['format'] # Set language if one pull from req_dict since language is from a header, not an arg language = None if 'headers' in req_dict and ('format' in param_dict and param_dict['format'] == "canonical"): if 'language' in req_dict['headers']: language = req_dict['headers']['language'] else: language = settings.LANGUAGE_CODE # If auth is in req dict, add it to param dict if 'auth' in req_dict: param_dict['auth'] = req_dict['auth'] # Get limit if one limit = None if 'params' in req_dict and 'limit' in req_dict['params']: limit = int(req_dict['params']['limit']) elif 'body' in req_dict and 'limit' in req_dict['body']: limit = int(req_dict['body']['limit']) # See if attachments should be included try: attachments = req_dict['params']['attachments'] except Exception: attachments = False # Create returned stmt list from the req dict stmt_result = complex_get(param_dict, limit, language, format, attachments) if format == 'exact': content_length = len(stmt_result) else: content_length = len(json.dumps(stmt_result)) # If attachments=True in req_dict then include the attachment payload and return different mime type if attachments: stmt_result, mime_type, content_length = build_response(stmt_result) resp = HttpResponse(stmt_result, content_type=mime_type, status=200) # Else attachments are false for the complex get so just dump the stmt_result else: if format == 'exact': result = stmt_result else: result = json.dumps(stmt_result) content_length = len(result) resp = HttpResponse(result, content_type=mime_type, status=200) return resp, content_length
def process_complex_get(req_dict): mime_type = "application/json" # Parse out params into single dict-GET data not in body param_dict = {} try: param_dict = req_dict['body'] if not isinstance(param_dict, dict): param_dict = convert_to_dict(param_dict) except KeyError: pass # no params in the body param_dict.update(req_dict['params']) format = param_dict['format'] # Set language if one pull from req_dict since language is from a header, not an arg language = None if 'headers' in req_dict and ('format' in param_dict and param_dict['format'] == "canonical"): if 'language' in req_dict['headers']: language = req_dict['headers']['language'] else: language = settings.LANGUAGE_CODE # If auth is in req dict, add it to param dict if 'auth' in req_dict: param_dict['auth'] = req_dict['auth'] # Get limit if one limit = None if 'params' in req_dict and 'limit' in req_dict['params']: limit = int(req_dict['params']['limit']) elif 'body' in req_dict and 'limit' in req_dict['body']: limit = int(req_dict['body']['limit']) # See if attachments should be included try: attachments = req_dict['params']['attachments'] except Exception: attachments = False # Create returned stmt list from the req dict stmt_result = complex_get(param_dict, limit, language, format, attachments) if format == 'exact': content_length = len(stmt_result) else: content_length = len(json.dumps(stmt_result)) # If attachments=True in req_dict then include the attachment payload and return different mime type if attachments: stmt_result, mime_type, content_length = build_response(stmt_result, content_length) resp = HttpResponse(stmt_result, content_type=''.join((mime_type, '; charset=utf-8')), status=200) # Else attachments are false for the complex get so just dump the stmt_result else: if format == 'exact': result = stmt_result else: result = json.dumps(stmt_result) content_length = len(result) resp = HttpResponse(result, content_type=''.join((mime_type, '; charset=utf-8')), status=200) return resp, content_length
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" ) 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())) if isinstance(req_dict['body'], basestring): req_dict['body'] = convert_to_dict(req_dict['body']) try: validator = StatementValidator(req_dict['body']) validator.validate() except Exception, e: raise BadRequest(e.message)
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") 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_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 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 __init__(self, data=None): # If incoming is a string, ast eval it (exception will be caught with whatever is calling validator) if data: self.data = convert_to_dict(data)
def complex_get(param_dict, limit, language, format, attachments): # Tests if value is True or "true" voidQ = 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']): q_auth = param_dict['auth']['agent'] # If oauth - set authority to look for as the user if q_auth.oauth_identifier: authQ = Q(authority=q_auth) | Q(authority=q_auth.get_user_from_oauth_group()) # Chain all of user's oauth clients as well else: oauth_clients = Agent.objects.filter(member__in=[q_auth]) authQ = Q(authority=q_auth) for client in oauth_clients: authQ = authQ | Q(authority=client.get_user_from_oauth_group()) 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 = Agent.objects.retrieve_or_create(**data)[0] # If agent is already a group, it can't be part of another group if agent.objectType == "Group": groups = [] # Since single agent, return all groups it is in 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(context_ca_parent__activity_id=param_dict['activity']) \ | Q(context_ca_grouping__activity_id=param_dict['activity']) \ | Q(context_ca_category__activity_id=param_dict['activity']) \ | Q(context_ca_other__activity_id=param_dict['activity']) \ | Q(object_substatement__object_activity__activity_id=param_dict['activity']) \ | Q(object_substatement__context_ca_parent__activity_id=param_dict['activity']) \ | Q(object_substatement__context_ca_grouping__activity_id=param_dict['activity']) \ | Q(object_substatement__context_ca_category__activity_id=param_dict['activity']) \ | Q(object_substatement__context_ca_other__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.prefetch_related('object_agent','object_activity','object_substatement','object_statementref','actor','verb','context_team','context_instructor','authority').filter(voidQ & untilQ & sinceQ & authQ & agentQ & verbQ & activityQ & registrationQ).distinct() stmtset = list(stmtset.values_list('statement_id', flat=True)) # only find references when a filter other than # since, until, or limit was used if reffilter: stmtset = stmtset + stmtrefsearch(stmtset) # 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 len(stmtset) > return_limit: return initial_cache_return(stmtset, stored_param, return_limit, language, format, attachments) else: return create_stmt_result(stmtset, stored_param, language, format)
def complex_get(param_dict, limit, language, format, attachments): # Tests if value is True or "true" voidQ = 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']): q_auth = param_dict['auth']['authority'] # If oauth - set authority to look for as the user if q_auth.oauth_identifier: authQ = Q(authority=q_auth) | Q(authority=q_auth.get_user_from_oauth_group()) # Chain all of user's oauth clients as well else: oauth_clients = Agent.objects.filter(member__in=[q_auth]) authQ = Q(authority=q_auth) for client in oauth_clients: authQ = authQ | Q(authority=client.get_user_from_oauth_group()) 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 = Agent.objects.retrieve_or_create(**data)[0] # If agent is already a group, it can't be part of another group if agent.objectType == "Group": groups = [] # Since single agent, return all groups it is in 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(voidQ & untilQ & sinceQ & authQ & agentQ & verbQ & activityQ & registrationQ).distinct() # only find references when a filter other than # since, until, or limit was used if reffilter: stmtset = findstmtrefs(stmtset, 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)