def agent_profile_get(req_dict): rogueparams = set(req_dict['params']) - set(["agent", "profileId", "since"]) if rogueparams: raise ParamError("The get agent profile request contained unexpected parameters: %s" % ", ".join(rogueparams)) validator = StatementValidator() if 'agent' in req_dict['params']: try: agent = json.loads(req_dict['params']['agent']) req_dict['params']['agent'] = agent except Exception: raise ParamError("agent param for agent profile is not valid") validator.validate_agent(agent, "agent param for agent profile") else: err_msg = "Error -- agent_profile - method = %s, but agent parameter missing.." % req_dict['method'] raise ParamError(err_msg) if 'since' in req_dict['params']: try: parse_datetime(req_dict['params']['since']) except (Exception, ISO8601Error): raise ParamError("Since parameter was not a valid ISO8601 timestamp") # Extra validation if oauth if req_dict['auth']['type'] == 'oauth': validate_oauth_state_or_profile_agent(req_dict, "profile") return req_dict
def validate_substatement(self, substmt): # Ensure incoming substmt is a dict and check allowed and required fields self.check_if_dict(substmt, "SubStatement") self.check_allowed_fields(sub_allowed_fields, substmt, "SubStatement") self.check_required_fields(sub_required_fields, substmt, "SubStatement") # If timestamp is included, ensure a valid time can be parsed if 'timestamp' in substmt: timestamp = substmt['timestamp'] try: parse_datetime(timestamp) except ISO8601Error as e: self.return_error("Timestamp error - There was an error while parsing the date from %s -- Error: %s" % (timestamp, e.message)) # Can't next substmts in other substmts - if not supplied it is an Activity if 'objectType' in substmt['object']: if substmt['object']['objectType'] == 'SubStatement': self.return_error("Cannot nest a SubStatement inside of another SubStatement") else: substmt['object']['objectType'] = 'Activity' # Validate agent, verb, and object self.validate_agent(substmt['actor'], 'actor') self.validate_object(substmt['object']) self.validate_verb(substmt['verb']) # If result included, validate it if 'result' in substmt: self.validate_result(substmt['result']) # If context included, validate it if 'context' in substmt: self.validate_context(substmt['context'], substmt['object'])
def get_headers(headers): r = {} if 'HTTP_UPDATED' in headers: try: r['updated'] = parse_datetime(headers['HTTP_UPDATED']) except (Exception, ISO8601Error): raise ParamError("Updated header was not a valid ISO8601 timestamp") elif 'updated' in headers: try: r['updated'] = parse_datetime(headers['updated']) except (Exception, ISO8601Error): raise ParamError("Updated header was not a valid ISO8601 timestamp") r['CONTENT_TYPE'] = headers.get('CONTENT_TYPE', '') if r['CONTENT_TYPE'] == '' and 'Content-Type' in headers: r['CONTENT_TYPE'] = headers['Content-Type'] # FireFox automatically adds ;charset=foo to the end of headers. This will strip it out if ';' in r['CONTENT_TYPE']: r['CONTENT_TYPE'] = r['CONTENT_TYPE'].split(';')[0] r['ETAG'] = get_etag_info(headers, required=False) if 'HTTP_AUTHORIZATION' in headers: r['Authorization'] = headers.get('HTTP_AUTHORIZATION', None) elif 'Authorization' in headers: r['Authorization'] = headers.get('Authorization', None) if 'Accept_Language' in headers: r['language'] = headers.get('Accept_Language', None) elif 'Accept-Language' in headers: r['language'] = headers['Accept-Language'] if 'X-Experience-API-Version' in headers: r['X-Experience-API-Version'] = headers['X-Experience-API-Version'] return r
def statements_get(req_dict): rogueparams = set(req_dict["params"]) - set( [ "statementId", "voidedStatementId", "agent", "verb", "activity", "registration", "related_activities", "related_agents", "since", "until", "limit", "format", "attachments", "ascending", ] ) if rogueparams: raise ParamError("The get statements request contained unexpected parameters: %s" % ", ".join(rogueparams)) formats = ["exact", "canonical", "ids"] if "params" in req_dict and "format" in req_dict["params"]: if req_dict["params"]["format"] not in formats: raise ParamError( "The format filter value (%s) was not one of the known values: %s" % (req_dict["params"]["format"], ",".join(formats)) ) else: req_dict["params"]["format"] = "exact" # StatementId could be for voided statement as well if "params" in req_dict and ("statementId" in req_dict["params"] or "voidedStatementId" in req_dict["params"]): req_dict["statementId"] = validate_statementId(req_dict) if "since" in req_dict["params"]: try: parse_datetime(req_dict["params"]["since"]) except (Exception, ISO8601Error): raise ParamError("Since parameter was not a valid ISO8601 timestamp") if "until" in req_dict["params"]: try: parse_datetime(req_dict["params"]["until"]) except (Exception, ISO8601Error): raise ParamError("Until parameter was not a valid ISO8601 timestamp") # Django converts all query values to string - make boolean depending on if client wants attachments or not # Only need to do this in GET b/c GET/more will have it saved in pickle information if "params" in req_dict and "attachments" in req_dict["params"]: if req_dict["params"]["attachments"].lower() == "true": req_dict["params"]["attachments"] = True else: req_dict["params"]["attachments"] = False else: req_dict["params"]["attachments"] = False return req_dict
def validate_statement(self, stmt): # Ensure dict was submitted as stmt and check allowed and required fields self.check_if_dict(stmt, "Statement") self.check_allowed_fields(statement_allowed_fields, stmt, "Statement") self.check_required_fields(statement_required_fields, stmt, "Statement") # If version included in stmt (usually in header instead) make sure it is 1.0.0 + if "version" in stmt: if isinstance(stmt["version"], basestring): version_regex = re.compile("^1\.0(\.\d+)?$") if not version_regex.match(stmt["version"]): self.return_error("%s is not a supported version" % stmt["version"]) else: self.return_error("Version must be a string") # If id included, make sure it is a valid UUID if "id" in stmt: self.validate_uuid(stmt["id"], "Statement id") # If timestamp included, make sure a valid date can be parsed from it if "timestamp" in stmt: timestamp = stmt["timestamp"] try: parse_datetime(timestamp) except ISO8601Error as e: self.return_error( "Timestamp error - There was an error while parsing the date from %s -- Error: %s" % (timestamp, e.message) ) # Validate the actor and verb self.validate_agent(stmt["actor"], "actor") self.validate_verb(stmt["verb"], stmt["object"]) # Validate the object stmt_object = stmt["object"] self.validate_object(stmt_object) # If the object is validated and has no objectType, set to Activity if not "objectType" in stmt_object: stmt["object"]["objectType"] = "Activity" # If result is included, validate it if "result" in stmt: self.validate_result(stmt["result"]) # If context is included, validate it if "context" in stmt: self.validate_context(stmt["context"], stmt_object) # If authority is included, validate it if "authority" in stmt: self.validate_agent(stmt["authority"], "authority") self.validate_authority(stmt["authority"]) # If attachments is included, validate it if "attachments" in stmt: self.validate_attachments(stmt["attachments"])
def validate_statement(self, stmt): # Ensure dict was submitted as stmt and check allowed and required fields self.check_if_dict(stmt, "Statement") self.check_allowed_fields(statement_allowed_fields, stmt, "Statement") self.check_required_fields(statement_required_fields, stmt, "Statement") # If version included in stmt (usually in header instead) make sure it is 1.0.0 + if 'version' in stmt: if isinstance(stmt['version'], basestring): version_regex = re.compile("^1\.0(\.\d+)?$") if not version_regex.match(stmt['version']): self.return_error("%s is not a supported version" % stmt['version']) else: self.return_error("Version must be a string") # If id included, make sure it is a valid UUID if 'id' in stmt: self.validate_uuid(stmt['id'], 'Statement id') # If timestamp included, make sure a valid date can be parsed from it if 'timestamp' in stmt: timestamp = stmt['timestamp'] try: parse_datetime(timestamp) except Exception as e: self.return_error("Timestamp error - There was an error while parsing the date from %s -- Error: %s" % (timestamp, e.message)) # Validate the actor and verb self.validate_agent(stmt['actor'], 'actor') self.validate_verb(stmt['verb'], stmt['object']) # Validate the object stmt_object = stmt['object'] self.validate_object(stmt_object) # If the object is validated and has no objectType, set to Activity if not 'objectType' in stmt_object: stmt['object']['objectType'] = 'Activity' # If result is included, validate it if 'result' in stmt: self.validate_result(stmt['result']) # If context is included, validate it if 'context' in stmt: self.validate_context(stmt['context'], stmt_object) # If authority is included, validate it if 'authority' in stmt: self.validate_agent(stmt['authority'], 'authority') if 'objectType' in stmt['authority'] and stmt['authority']['objectType'] == 'Group': self.validate_authority_group(stmt['authority']) # If attachments is included, validate it if 'attachments' in stmt: self.validate_attachments(stmt['attachments'])
def get_headers(headers): header_dict = {} # Get updated header if 'HTTP_UPDATED' in headers: try: header_dict['updated'] = parse_datetime( headers.pop('HTTP_UPDATED')) except (Exception, ISO8601Error): raise ParamError( "Updated header was not a valid ISO8601 timestamp") elif 'updated' in headers: try: header_dict['updated'] = parse_datetime(headers.pop('updated')) except (Exception, ISO8601Error): raise ParamError( "Updated header was not a valid ISO8601 timestamp") # Get content type header header_dict['CONTENT_TYPE'] = headers.pop('CONTENT_TYPE', None) if not header_dict['CONTENT_TYPE'] and 'Content-Type' in headers: header_dict['CONTENT_TYPE'] = headers.pop('Content-Type') # Could not exist with deletes if header_dict['CONTENT_TYPE']: # FireFox automatically adds ;charset=foo to the end of headers. This # will strip it out if ';' in header_dict['CONTENT_TYPE'] and 'boundary' not in header_dict['CONTENT_TYPE']: header_dict['CONTENT_TYPE'] = header_dict['CONTENT_TYPE'].split(';')[ 0] # Get etag header_dict['ETAG'] = get_etag_info(headers, required=False) # Get authorization - don't pop off - needed for setting authorization if 'HTTP_AUTHORIZATION' in headers: header_dict['Authorization'] = headers.get('HTTP_AUTHORIZATION') elif 'Authorization' in headers: header_dict['Authorization'] = headers.get('Authorization') # Get language if 'Accept_Language' in headers: header_dict['language'] = headers.pop('Accept_Language') elif 'Accept-Language' in headers: header_dict['language'] = headers.pop('Accept-Language') elif 'HTTP_ACCEPT_LANGUAGE' in headers: header_dict['language'] = headers.pop('HTTP_ACCEPT_LANGUAGE') # Get xapi version if 'X-Experience-API-Version' in headers: header_dict[ 'X-Experience-API-Version'] = headers.pop('X-Experience-API-Version') return header_dict
def convert_to_datetime_object(self, timestr): try: date_object = parse_datetime(timestr) except ValueError as e: raise ParamError("An error has occurred. Time format does not match. %s -- Error: %s" % (timestr, e.message)) return date_object
def convert_to_datetime_object(timestr): try: date_object = parse_datetime(timestr) except ValueError as e: raise ParamError( "There was an error while parsing the date from %s -- Error: %s" % (timestr, e.message)) return date_object
def convert_to_utc(timestr): try: date_object = parse_datetime(timestr) except ValueError as e: raise ParamError( "There was an error while parsing the date from %s -- Error: %s" % (timestr, e.message)) return date_object
def activity_state_get(req_dict): rogueparams = set(req_dict['params']) - set( ["activityId", "agent", "stateId", "registration", "since"]) if rogueparams and not ignore_rogue_params: raise ParamError( "The get activity state request contained unexpected parameters: %s" % ", ".join(rogueparams)) validator = StatementValidator() if 'activityId' in req_dict['params']: validator.validate_iri(req_dict['params']['activityId'], "activityId param for activity state") else: err_msg = "Error -- activity_state - method = %s, but activityId parameter is missing.." % req_dict[ 'method'] raise ParamError(err_msg) if 'registration' in req_dict['params']: validator.validate_uuid(req_dict['params']['registration'], "registration param for activity state") if 'agent' in req_dict['params']: try: agent = convert_to_datatype(req_dict['params']['agent']) req_dict['params']['agent'] = agent except Exception: raise ParamError("agent param %s is not valid" % \ req_dict['params']['agent']) validator.validate_agent(agent, "Agent param") else: err_msg = "Error -- activity_state - method = %s, but agent parameter is missing.." % req_dict[ 'method'] raise ParamError(err_msg) if 'since' in req_dict['params']: try: parse_datetime(req_dict['params']['since']) except (Exception, ISO8601Error): raise ParamError( "Since parameter was not a valid ISO8601 timestamp") # Extra validation if oauth if req_dict['auth']['type'] == 'oauth': validate_oauth_for_documents(req_dict, "state") return req_dict
def statements_get(req_dict): rogueparams = set(req_dict['params']) - set(["statementId", "voidedStatementId", "agent", "verb", "activity", "registration", "related_activities", "related_agents", "since", "until", "limit", "format", "attachments", "ascending"]) if rogueparams: raise ParamError( "The get statements request contained unexpected parameters: %s" % ", ".join(rogueparams)) formats = ['exact', 'canonical', 'ids'] if 'params' in req_dict and 'format' in req_dict['params']: if req_dict['params']['format'] not in formats: raise ParamError("The format filter value (%s) was not one of the known values: %s" % ( req_dict['params']['format'], ','.join(formats))) else: req_dict['params']['format'] = 'exact' # StatementId could be for voided statement as well if 'params' in req_dict and ('statementId' in req_dict['params'] or 'voidedStatementId' in req_dict['params']): req_dict['statementId'] = validate_statementId(req_dict) if 'since' in req_dict['params']: try: parse_datetime(req_dict['params']['since']) except (Exception, ISO8601Error): raise ParamError( "Since parameter was not a valid ISO8601 timestamp") if 'until' in req_dict['params']: try: parse_datetime(req_dict['params']['until']) except (Exception, ISO8601Error): raise ParamError( "Until parameter was not a valid ISO8601 timestamp") # Django converts all query values to string - make boolean depending on if client wants attachments or not # Only need to do this in GET b/c GET/more will have it saved in pickle # information if 'params' in req_dict and 'attachments' in req_dict['params']: if req_dict['params']['attachments'].lower() == 'true': req_dict['params']['attachments'] = True else: req_dict['params']['attachments'] = False else: req_dict['params']['attachments'] = False return req_dict
def convert_to_datetime_object(self, timestr): try: date_object = parse_datetime(timestr) except ValueError as e: raise ParamError( "An error has occurred. Time format does not match. %s -- Error: %s" % (timestr, e.message)) return date_object
def activity_state_get(req_dict): rogueparams = set(req_dict['params']) - set(["activityId", "agent", "stateId", "registration", "since"]) if rogueparams: raise ParamError( "The get activity state request contained unexpected parameters: %s" % ", ".join(rogueparams)) validator = StatementValidator() if 'activityId' in req_dict['params']: validator.validate_iri( req_dict['params']['activityId'], "activityId param for activity state") else: err_msg = "Error -- activity_state - method = %s, but activityId parameter is missing.." % req_dict[ 'method'] raise ParamError(err_msg) if 'registration' in req_dict['params']: validator.validate_uuid( req_dict['params']['registration'], "registration param for activity state") if 'agent' in req_dict['params']: try: agent = convert_to_datatype(req_dict['params']['agent']) req_dict['params']['agent'] = agent except Exception: raise ParamError("agent param %s is not valid" % \ req_dict['params']['agent']) validator.validate_agent(agent, "Agent param") else: err_msg = "Error -- activity_state - method = %s, but agent parameter is missing.." % req_dict[ 'method'] raise ParamError(err_msg) if 'since' in req_dict['params']: try: parse_datetime(req_dict['params']['since']) except (Exception, ISO8601Error): raise ParamError( "Since parameter was not a valid ISO8601 timestamp") # Extra validation if oauth if req_dict['auth']['type'] == 'oauth': validate_oauth_for_documents(req_dict, "state") return req_dict
def activity_profile_get(req_dict): rogueparams = set(req_dict['params']) - set(["activityId", "profileId", "since"]) if rogueparams: raise ParamError("The get activity profile request contained unexpected parameters: %s" % ", ".join(rogueparams)) validator = StatementValidator() if 'activityId' in req_dict['params']: validator.validate_iri(req_dict['params']['activityId'], "activityId param for activity profile") else: err_msg = "Error -- activity_profile - method = %s, but activityId parameter missing.." % req_dict['method'] raise ParamError(err_msg) if 'since' in req_dict['params']: try: parse_datetime(req_dict['params']['since']) except (Exception, ISO8601Error): raise ParamError("Since parameter was not a valid ISO8601 timestamp") return req_dict
def statements_get(req_dict): rogueparams = set(req_dict['params']) - set(["statementId","voidedStatementId","agent", "verb", "activity", "registration", "related_activities", "related_agents", "since", "until", "limit", "format", "attachments", "ascending"]) if rogueparams: raise ParamError("The get statements request contained unexpected parameters: %s" % ", ".join(rogueparams)) formats = ['exact', 'canonical', 'ids'] if 'params' in req_dict and 'format' in req_dict['params']: if req_dict['params']['format'] not in formats: raise ParamError("The format filter value (%s) was not one of the known values: %s" % (req_dict['params']['format'], ','.join(formats))) else: req_dict['params']['format'] = 'exact' # StatementId could be for voided statement as well if 'params' in req_dict and ('statementId' in req_dict['params'] or 'voidedStatementId' in req_dict['params']): req_dict['statementId'] = validate_statementId(req_dict) if 'since' in req_dict['params']: try: parse_datetime(req_dict['params']['since']) except (Exception, ISO8601Error): raise ParamError("Since parameter was not a valid ISO8601 timestamp") if 'until' in req_dict['params']: try: parse_datetime(req_dict['params']['until']) except (Exception, ISO8601Error): raise ParamError("Until parameter was not a valid ISO8601 timestamp") # Django converts all query values to string - make boolean depending on if client wants attachments or not # Only need to do this in GET b/c GET/more will have it saved in pickle information if 'params' in req_dict and 'attachments' in req_dict['params']: if req_dict['params']['attachments'].lower() == 'true': req_dict['params']['attachments'] = True else: req_dict['params']['attachments'] = False else: req_dict['params']['attachments'] = False return req_dict
def validate_substatement(self, substmt): # Ensure incoming substmt is a dict and check allowed and required # fields self.check_if_dict(substmt, "SubStatement") self.check_allowed_fields(sub_allowed_fields, substmt, "SubStatement") self.check_required_fields(sub_required_fields, substmt, "SubStatement") # If timestamp is included, ensure a valid time can be parsed if 'timestamp' in substmt: timestamp = substmt['timestamp'] try: parse_datetime(timestamp) except Exception as e: self.return_error( "Timestamp error - There was an error while parsing the date from %s -- Error: %s" % (timestamp, e.message)) # Can't next substmts in other substmts - if not supplied it is an # Activity if 'objectType' in substmt['object']: if substmt['object']['objectType'] == 'SubStatement': self.return_error( "Cannot nest a SubStatement inside of another SubStatement" ) else: substmt['object']['objectType'] = 'Activity' # Validate agent, verb, and object self.validate_agent(substmt['actor'], 'actor') self.validate_object(substmt['object']) self.validate_verb(substmt['verb']) # If result included, validate it if 'result' in substmt: self.validate_result(substmt['result']) # If context included, validate it if 'context' in substmt: self.validate_context(substmt['context'], substmt['object'])
def validate_substatement(self, substmt): # Ensure incoming substmt is a dict and check allowed and required # fields self.check_if_dict(substmt, "SubStatement") self.check_allowed_fields(sub_allowed_fields, substmt, "SubStatement") self.check_required_fields(sub_required_fields, substmt, "SubStatement") # If timestamp is included, ensure a valid time can be parsed if "timestamp" in substmt: timestamp = substmt["timestamp"] try: parse_datetime(timestamp) except Exception as e: self.return_error( "Timestamp error - There was an error while parsing the date from %s -- Error: %s" % (timestamp, e.message) ) # Can't next substmts in other substmts - if not supplied it is an # Activity if "objectType" in substmt["object"]: if substmt["object"]["objectType"] == "SubStatement": self.return_error("Cannot nest a SubStatement inside of another SubStatement") else: substmt["object"]["objectType"] = "Activity" # Validate agent, verb, and object self.validate_agent(substmt["actor"], "actor") self.validate_object(substmt["object"]) self.validate_verb(substmt["verb"]) # If result included, validate it if "result" in substmt: self.validate_result(substmt["result"]) # If context included, validate it if "context" in substmt: self.validate_context(substmt["context"], substmt["object"])
def activity_state_get(req_dict): rogueparams = set(req_dict["params"]) - set(["activityId", "agent", "stateId", "registration", "since"]) if rogueparams: raise ParamError("The get activity state request contained unexpected parameters: %s" % ", ".join(rogueparams)) validator = StatementValidator() if "activityId" in req_dict["params"]: validator.validate_iri(req_dict["params"]["activityId"], "activityId param for activity state") else: err_msg = "Error -- activity_state - method = %s, but activityId parameter is missing.." % req_dict["method"] raise ParamError(err_msg) if "registration" in req_dict["params"]: validator.validate_uuid(req_dict["params"]["registration"], "registration param for activity state") if "agent" in req_dict["params"]: try: agent = json.loads(req_dict["params"]["agent"]) req_dict["params"]["agent"] = agent except Exception: raise ParamError("agent param for activity state is not valid") validator.validate_agent(agent, "Activity state agent param") else: err_msg = "Error -- activity_state - method = %s, but agent parameter is missing.." % req_dict["method"] raise ParamError(err_msg) if "since" in req_dict["params"]: try: parse_datetime(req_dict["params"]["since"]) except (Exception, ISO8601Error): raise ParamError("Since parameter was not a valid ISO8601 timestamp") # Extra validation if oauth if req_dict["auth"]["type"] == "oauth": validate_oauth_state_or_profile_agent(req_dict, "state") return req_dict
def get_headers(headers): r = {} if 'HTTP_UPDATED' in headers: try: r['updated'] = parse_datetime(headers['HTTP_UPDATED']) except (Exception, ISO8601Error): raise ParamError( "Updated header was not a valid ISO8601 timestamp") elif 'updated' in headers: try: r['updated'] = parse_datetime(headers['updated']) except (Exception, ISO8601Error): raise ParamError( "Updated header was not a valid ISO8601 timestamp") r['CONTENT_TYPE'] = headers.get('CONTENT_TYPE', '') if r['CONTENT_TYPE'] == '' and 'Content-Type' in headers: r['CONTENT_TYPE'] = headers['Content-Type'] # FireFox automatically adds ;charset=foo to the end of headers. This will strip it out if ';' in r['CONTENT_TYPE']: r['CONTENT_TYPE'] = r['CONTENT_TYPE'].split(';')[0] r['ETAG'] = get_etag_info(headers, required=False) if 'HTTP_AUTHORIZATION' in headers: r['Authorization'] = headers.get('HTTP_AUTHORIZATION', None) elif 'Authorization' in headers: r['Authorization'] = headers.get('Authorization', None) if 'Accept_Language' in headers: r['language'] = headers.get('Accept_Language', None) elif 'Accept-Language' in headers: r['language'] = headers['Accept-Language'] if 'X-Experience-API-Version' in headers: r['X-Experience-API-Version'] = headers['X-Experience-API-Version'] return r
def set_order_complete(order_id: int, complete_time: str): order = db.get_order_by_id(order_id) delivery = db.get_delivery_by_id(order.delivery_id) complete_datetime = isodatetime.parse_datetime(complete_time) if delivery.previous_order_complete_time is None: delivery_time = (complete_datetime - delivery.assign_time).total_seconds() else: delivery_time = ( complete_datetime - delivery.previous_order_complete_time).total_seconds() delivery.previous_order_complete_time = complete_datetime db.set_order_complete(order_id, delivery_time) user_orders = db.get_active_courier_orders(order.courier_id) if len(user_orders) == 0: delivery.is_complete = True db.update_delivery(delivery)
def test_create_user_ok(): with database_mock() as db: assert db.collection("users").all().count() == 0 response = client.post( "/users/", json={ "username": mocks.users.alice.username, "password": ALICE_PASSWORD, "email": mocks.users.alice.email, }, ) assert response.status_code == status.HTTP_201_CREATED assert response.json()["username"] == mocks.users.alice.username assert response.json()["email"] == mocks.users.alice.email assert not response.json()["email_is_confirmed"] joined_at = isodatetime.parse_datetime(response.json()["joined_at"]) assert joined_at.today assert "_key" in response.json().keys()
def validate_statement(self, stmt): # Ensure dict was submitted as stmt and check allowed and required # fields self.check_if_dict(stmt, "Statement") self.check_allowed_fields(statement_allowed_fields, stmt, "Statement") self.check_required_fields(statement_required_fields, stmt, "Statement") # If version included in stmt (usually in header instead) make sure it # is 1.0.0 + if 'version' in stmt: if isinstance(stmt['version'], basestring): version_regex = re.compile("^1\.0(\.\d+)?$") if not version_regex.match(stmt['version']): self.return_error("%s is not a supported version" % stmt['version']) else: self.return_error("Version must be a string") # If id included, make sure it is a valid UUID if 'id' in stmt: self.validate_uuid(stmt['id'], 'Statement id') # If timestamp included, make sure a valid date can be parsed from it if 'timestamp' in stmt: timestamp = stmt['timestamp'] try: parse_datetime(timestamp) except Exception as e: self.return_error( "Timestamp error - There was an error while parsing the date from %s -- Error: %s" % (timestamp, e.message)) # If stored included, make sure a valid date can be parsed from it if 'stored' in stmt: stored = stmt['stored'] try: parse_datetime(stored) except Exception as e: self.return_error( "Stored error - There was an error while parsing the date from %s -- Error: %s" % (stored, e.message)) # Validate the actor and verb self.validate_agent(stmt['actor'], 'actor') self.validate_verb(stmt['verb'], stmt['object']) # Validate the object stmt_object = stmt['object'] self.validate_object(stmt_object) # If the object is validated and has no objectType, set to Activity if 'objectType' not in stmt_object: stmt['object']['objectType'] = 'Activity' # If result is included, validate it if 'result' in stmt: self.validate_result(stmt['result']) # If context is included, validate it if 'context' in stmt: self.validate_context(stmt['context'], stmt_object) # If authority is included, validate it if 'authority' in stmt: self.validate_agent(stmt['authority'], 'authority') if 'objectType' in stmt['authority'] and stmt['authority'][ 'objectType'] == 'Group': self.validate_authority_group(stmt['authority']) # If attachments is included, validate it if 'attachments' in stmt: self.validate_attachments(stmt['attachments'])
def parse_duration(datestring): """ Parses an ISO 8601 durations into datetime.timedelta or Duration objects. If the ISO date string does not contain years or months, a timedelta instance is returned, else a Duration instance is returned. The following duration formats are supported: -PnnW duration in weeks -PnnYnnMnnDTnnHnnMnnS complete duration specification -PYYYYMMDDThhmmss basic alternative complete date format -PYYYY-MM-DDThh:mm:ss extended alternative complete date format -PYYYYDDDThhmmss basic alternative ordinal date format -PYYYY-DDDThh:mm:ss extended alternative ordinal date format The '-' is optional. Limitations: ISO standard defines some restrictions about where to use fractional numbers and which component and format combinations are allowed. This parser implementation ignores all those restrictions and returns something when it is able to find all necessary components. In detail: it does not check, whether only the last component has fractions. it allows weeks specified with all other combinations The alternative format does not support durations with years, months or days set to 0. """ if not isinstance(datestring, str): raise TypeError("Expecting a string %r" % datestring) match = ISO8601_PERIOD_REGEX.match(datestring) if not match: # try alternative format: if datestring.startswith("P"): durdt = parse_datetime(datestring[1:]) if durdt.year != 0 or durdt.month != 0: # create Duration ret = Duration(days=durdt.day, seconds=durdt.second, microseconds=durdt.microsecond, minutes=durdt.minute, hours=durdt.hour, months=durdt.month, years=durdt.year) else: # FIXME: currently not possible in alternative format # create timedelta ret = timedelta(days=durdt.day, seconds=durdt.second, microseconds=durdt.microsecond, minutes=durdt.minute, hours=durdt.hour) return ret raise ISO8601Error("Unable to parse duration string %r" % datestring) groups = match.groupdict() for key, val in list(groups.items()): if key not in ('separator', 'sign'): if val is None: groups[key] = "0n" #print groups[key] groups[key] = float(groups[key][:-1].replace(',', '.')) if groups["years"] == 0 and groups["months"] == 0: ret = timedelta(days=groups["days"], hours=groups["hours"], minutes=groups["minutes"], seconds=groups["seconds"], weeks=groups["weeks"]) if groups["sign"] == '-': ret = timedelta(0) - ret else: ret = Duration(years=groups["years"], months=groups["months"], days=groups["days"], hours=groups["hours"], minutes=groups["minutes"], seconds=groups["seconds"], weeks=groups["weeks"]) if groups["sign"] == '-': ret = Duration(0) - ret return ret
if not validate_uuid(req_dict['params']['registration']): raise ParamError("%s is not a valid uuid for the registration parameter") if 'agent' in req_dict['params']: try: agent = json.loads(req_dict['params']['agent']) except Exception, e: raise ParamError("agent param for activity state is not valid") validator.validate_agent(agent, "Activity state agent param") else: err_msg = "Error -- activity_state - method = %s, but agent parameter is missing.." % req_dict['method'] raise ParamError(err_msg) if 'since' in req_dict['params']: try: parse_datetime(req_dict['params']['since']) except (Exception, ISO8601Error): raise ParamError("Since parameter was not a valid ISO8601 timestamp") # Extra validation if oauth if req_dict['auth']['type'] == 'oauth': validate_oauth_state_or_profile_agent(req_dict, "state") return req_dict @auth def activity_state_delete(req_dict): rogueparams = set(req_dict['params']) - set(["activityId", "agent", "stateId", "registration"]) if rogueparams: raise ParamError("The delete activity state request contained unexpected parameters: %s" % ", ".join(rogueparams))
def parse_interval(interval_string): if not isinstance(interval_string, string_types): raise TypeError("Expecing a string") segment_count = interval_string.count(SEGMENT_DELIM) if segment_count < 1 or segment_count > 2: raise ISO8601Error( "Improper number of interval string segments. Must have 1 or 2") segments = interval_string.split(SEGMENT_DELIM) for idx, seg in enumerate(segments): if len(seg) == 0: return ISO8601Error("Interval segment index %s was empty" % idx) count = None if len(segments) == 3: # Rn/start/end # Rn/start/duration # Rn/duration/end s0 = segments[0] match = ISO8601_REPEAT_REGEX.match(s0) if not match: raise ISO8601Error("Repeat notation did not match expected") groups = match.groupdict() count = groups.get("count", None) if len(count) > 0: count = int(count) segments = segments[1:] s0 = segments[0] s1 = segments[1] # remaining segments are either # 1) start/end. # start must be a fully specified datetime format # end can either be a time, date, or datetime # 2) start/duration # start must be a fully specified datetime format # duration must be a valid duration format # 3) duration/end # duration must be a valid duration format # end must be a fully specified datetime format start = None end = None duration = None try: # (1) start = parse_datetime(s0) print("second to last term is a datetime") except: try: duration = parse_duration(s0) print("second to last term is a datetime") except: raise ISO8601Error( "First term after repeat must be either " + "a fully specified datetime or a valid duration") # look at last term # this isn't the prettiest way to do it, but it is effective # could also build the regexes from other modules, but delegation avoids code duplication if start: # last term must be a duration, date, time or datetime try: end = parse_datetime(s1) print("last term is a datetime") except: try: end = parse_date(s1) print("last term is a date") except: try: end = parse_time(s1) print("last term is a time") except: try: duration = parse_duration(s1) print("last term is a duration") except: raise ISO8601Error( "When first term after repeat is a datetime, " + "last term must be either a duration, datetime, date, or time" ) elif duration: # last term must be the end datetime try: end = parse_datetime(s1) except: raise ISO8601Error("If first term after repeat is a duration, " + "last term must be a datetime") interval = Interval(start=start, end=end, duration=duration, repeat=count) print(interval)
def statements_get(req_dict): rogueparams = set(req_dict['params']) - set([ "statementId", "voidedStatementId", "agent", "verb", "activity", "registration", "related_activities", "related_agents", "since", "until", "limit", "format", "attachments", "ascending" ]) if rogueparams and not ignore_rogue_params: raise ParamError( "The get statements request contained unexpected parameters: %s" % ", ".join(rogueparams)) validator = StatementValidator() if 'agent' in req_dict['params']: try: agent = convert_to_datatype(req_dict['params']['agent']) req_dict['params']['agent'] = agent except Exception: raise ParamError("agent param %s is not valid" % \ req_dict['params']['agent']) validator.validate_agent(agent, "Agent param") formats = ['exact', 'canonical', 'ids'] if 'format' in req_dict['params']: if req_dict['params']['format'] not in formats: raise ParamError( "The format filter value (%s) was not one of the known values: %s" % (req_dict['params']['format'], ','.join(formats))) else: req_dict['params']['format'] = 'exact' # StatementId could be for voided statement as well if 'statementId' in req_dict['params'] or 'voidedStatementId' in req_dict[ 'params']: req_dict['statementId'] = validate_statementId(req_dict) if 'since' in req_dict['params']: try: parse_datetime(req_dict['params']['since']) except (Exception, ISO8601Error): raise ParamError( "since parameter was not a valid ISO8601 timestamp") if 'until' in req_dict['params']: try: parse_datetime(req_dict['params']['until']) except (Exception, ISO8601Error): raise ParamError( "until parameter was not a valid ISO8601 timestamp") if 'ascending' in req_dict['params']: if req_dict['params']['ascending'].lower() == 'true': req_dict['params']['ascending'] = True elif req_dict['params']['ascending'].lower() == 'false': req_dict['params']['ascending'] = False else: raise ParamError("ascending parameter was not a boolean value") else: req_dict['params']['ascending'] = False if 'related_agents' in req_dict['params']: if req_dict['params']['related_agents'].lower() == 'true': req_dict['params']['related_agents'] = True elif req_dict['params']['related_agents'].lower() == 'false': req_dict['params']['related_agents'] = False else: raise ParamError( "related_agents parameter was not a boolean value") else: req_dict['params']['related_agents'] = False if 'related_activities' in req_dict['params']: if req_dict['params']['related_activities'].lower() == 'true': req_dict['params']['related_activities'] = True elif req_dict['params']['related_activities'].lower() == 'false': req_dict['params']['related_activities'] = False else: raise ParamError( "related_activities parameter was not a boolean value") else: req_dict['params']['related_activities'] = False if 'attachments' in req_dict['params']: if req_dict['params']['attachments'].lower() == 'true': req_dict['params']['attachments'] = True elif req_dict['params']['attachments'].lower() == 'false': req_dict['params']['attachments'] = False else: raise ParamError("attachments parameter was not a boolean value") else: req_dict['params']['attachments'] = False if 'limit' in req_dict['params']: try: req_dict['params']['limit'] = int(req_dict['params']['limit']) except Exception: raise ParamError("limit parameter was not a non-negative integer") else: if req_dict['params']['limit'] < 0: raise ParamError( "limit parameter was not a non-negative integer") else: req_dict['params']['limit'] = 0 if 'registration' in req_dict['params']: validator.validate_uuid(req_dict['params']['registration'], "Registration param") if 'verb' in req_dict['params']: validator.validate_iri(req_dict['params']['verb'], "verb param") return req_dict
def parse_duration(datestring): """ Parses an ISO 8601 durations into datetime.timedelta or Duration objects. If the ISO date string does not contain years or months, a timedelta instance is returned, else a Duration instance is returned. The following duration formats are supported: -PnnW duration in weeks -PnnYnnMnnDTnnHnnMnnS complete duration specification -PYYYYMMDDThhmmss basic alternative complete date format -PYYYY-MM-DDThh:mm:ss extended alternative complete date format -PYYYYDDDThhmmss basic alternative ordinal date format -PYYYY-DDDThh:mm:ss extended alternative ordinal date format The '-' is optional. Limitations: ISO standard defines some restrictions about where to use fractional numbers and which component and format combinations are allowed. This parser implementation ignores all those restrictions and returns something when it is able to find all necessary components. In detail: it does not check, whether only the last component has fractions. it allows weeks specified with all other combinations The alternative format does not support durations with years, months or days set to 0. """ if not isinstance(datestring, basestring): raise TypeError("Expecting a string %r" % datestring) match = ISO8601_PERIOD_REGEX.match(datestring) if not match: # try alternative format: if datestring.startswith("P"): durdt = parse_datetime(datestring[1:]) if durdt.year != 0 or durdt.month != 0: # create Duration ret = Duration(days=durdt.day, seconds=durdt.second, microseconds=durdt.microsecond, minutes=durdt.minute, hours=durdt.hour, months=durdt.month, years=durdt.year) else: # FIXME: currently not possible in alternative format # create timedelta ret = timedelta(days=durdt.day, seconds=durdt.second, microseconds=durdt.microsecond, minutes=durdt.minute, hours=durdt.hour) return ret raise ISO8601Error("Unable to parse duration string %r" % datestring) groups = match.groupdict() for key, val in groups.items(): if key not in ('separator', 'sign'): if val is None: groups[key] = "0n" #print groups[key] if key in ('years', 'months'): groups[key] = Decimal(groups[key][:-1].replace(',', '.')) else: # these values are passed into a timedelta object, which works with floats. groups[key] = float(groups[key][:-1].replace(',', '.')) if groups["years"] == 0 and groups["months"] == 0: ret = timedelta(days=groups["days"], hours=groups["hours"], minutes=groups["minutes"], seconds=groups["seconds"], weeks=groups["weeks"]) if groups["sign"] == '-': ret = timedelta(0) - ret else: ret = Duration(years=groups["years"], months=groups["months"], days=groups["days"], hours=groups["hours"], minutes=groups["minutes"], seconds=groups["seconds"], weeks=groups["weeks"]) if groups["sign"] == '-': ret = Duration(0) - ret return ret
def statements_get(req_dict): rogueparams = set(req_dict['params']) - set(["statementId", "voidedStatementId", "agent", "verb", "activity", "registration", "related_activities", "related_agents", "since", "until", "limit", "format", "attachments", "ascending"]) if rogueparams: raise ParamError( "The get statements request contained unexpected parameters: %s" % ", ".join(rogueparams)) validator = StatementValidator() if 'agent' in req_dict['params']: try: agent = convert_to_datatype(req_dict['params']['agent']) req_dict['params']['agent'] = agent except Exception: raise ParamError("agent param %s is not valid" % \ req_dict['params']['agent']) validator.validate_agent(agent, "Agent param") formats = ['exact', 'canonical', 'ids'] if 'format' in req_dict['params']: if req_dict['params']['format'] not in formats: raise ParamError("The format filter value (%s) was not one of the known values: %s" % ( req_dict['params']['format'], ','.join(formats))) else: req_dict['params']['format'] = 'exact' # StatementId could be for voided statement as well if 'statementId' in req_dict['params'] or 'voidedStatementId' in req_dict['params']: req_dict['statementId'] = validate_statementId(req_dict) if 'since' in req_dict['params']: try: parse_datetime(req_dict['params']['since']) except (Exception, ISO8601Error): raise ParamError( "since parameter was not a valid ISO8601 timestamp") if 'until' in req_dict['params']: try: parse_datetime(req_dict['params']['until']) except (Exception, ISO8601Error): raise ParamError( "until parameter was not a valid ISO8601 timestamp") if 'ascending' in req_dict['params']: if req_dict['params']['ascending'].lower() == 'true': req_dict['params']['ascending'] = True elif req_dict['params']['ascending'].lower() == 'false': req_dict['params']['ascending'] = False else: raise ParamError( "ascending parameter was not a boolean value") else: req_dict['params']['ascending'] = False if 'related_agents' in req_dict['params']: if req_dict['params']['related_agents'].lower() == 'true': req_dict['params']['related_agents'] = True elif req_dict['params']['related_agents'].lower() == 'false': req_dict['params']['related_agents'] = False else: raise ParamError( "related_agents parameter was not a boolean value") else: req_dict['params']['related_agents'] = False if 'related_activities' in req_dict['params']: if req_dict['params']['related_activities'].lower() == 'true': req_dict['params']['related_activities'] = True elif req_dict['params']['related_activities'].lower() == 'false': req_dict['params']['related_activities'] = False else: raise ParamError( "related_activities parameter was not a boolean value") else: req_dict['params']['related_activities'] = False if 'attachments' in req_dict['params']: if req_dict['params']['attachments'].lower() == 'true': req_dict['params']['attachments'] = True elif req_dict['params']['attachments'].lower() == 'false': req_dict['params']['attachments'] = False else: raise ParamError( "attachments parameter was not a boolean value") else: req_dict['params']['attachments'] = False if 'limit' in req_dict['params']: try: req_dict['params']['limit'] = int(req_dict['params']['limit']) except Exception: raise ParamError( "limit parameter was not a non-negative integer") else: if req_dict['params']['limit'] < 0: raise ParamError( "limit parameter was not a non-negative integer") else: req_dict['params']['limit'] = 0 if 'registration' in req_dict['params']: validator.validate_uuid(req_dict['params']['registration'], "Registration param") if 'verb' in req_dict['params']: validator.validate_iri( req_dict['params']['verb'], "verb param") return req_dict