def project_new_post(auth, **kwargs): user = auth.user data = request.get_json() title = strip_html(data.get('title')) title = title.strip() category = data.get('category', 'project') template = data.get('template') description = strip_html(data.get('description')) if not title or len(title) > 200: raise HTTPError(http.BAD_REQUEST) if template: original_node = Node.load(template) changes = { 'title': title, 'category': category, 'template_node': original_node, } if description: changes['description'] = description project = original_node.use_as_template(auth=auth, changes={ template: changes, }) else: project = new_node(category, title, user, description) return {'projectUrl': project.url}, http.CREATED
def test_bulk_creates_children_and_sanitizes_html_logged_in_owner(self): title = "<em>Cool</em> <strong>Project</strong>" description = 'An <script>alert("even cooler")</script> child' res = self.app.post_json_api( self.url, { "data": [ { "type": "nodes", "attributes": { "title": title, "description": description, "category": "project", "public": True, }, } ] }, auth=self.user.auth, bulk=True, ) child_id = res.json["data"][0]["id"] assert_equal(res.status_code, 201) url = "/{}nodes/{}/".format(API_BASE, child_id) res = self.app.get(url, auth=self.user.auth) assert_equal(res.json["data"]["attributes"]["title"], strip_html(title)) assert_equal(res.json["data"]["attributes"]["description"], strip_html(description)) assert_equal(res.json["data"]["attributes"]["category"], "project") self.project.reload() child_id = res.json["data"]["id"] assert_equal(child_id, self.project.nodes[0]._id) assert_equal(Node.load(child_id).logs[0].action, NodeLog.PROJECT_CREATED)
def new_node(category, title, user, description=None, parent=None): """Create a new project or component. :param str category: Node category :param str title: Node title :param User user: User object :param str description: Node description :param Node project: Optional parent object :return Node: Created node """ category = category title = strip_html(title.strip()) if description: description = strip_html(description.strip()) node = Node( title=title, category=category, creator=user, description=description, parent=parent ) node.save() return node
def test_bulk_creates_children_and_sanitizes_html_logged_in_owner(self): title = '<em>Cool</em> <strong>Project</strong>' description = 'An <script>alert("even cooler")</script> child' res = self.app.post_json_api(self.url, { 'data': [{ 'type': 'nodes', 'attributes': { 'title': title, 'description': description, 'category': 'project', 'public': True } }] }, auth=self.user.auth, bulk=True) child_id = res.json['data'][0]['id'] assert_equal(res.status_code, 201) url = '/{}nodes/{}/'.format(API_BASE, child_id) res = self.app.get(url, auth=self.user.auth) assert_equal(res.json['data']['attributes']['title'], strip_html(title)) assert_equal(res.json['data']['attributes']['description'], strip_html(description)) assert_equal(res.json['data']['attributes']['category'], 'project') self.project.reload() child_id = res.json['data']['id'] assert_equal(child_id, self.project.nodes[0]._id) assert_equal( Node.load(child_id).logs.latest().action, NodeLog.PROJECT_CREATED)
def test_bulk_creates_children_and_sanitizes_html_logged_in_owner(self, app, user, project, url): title = '<em>Reasoning</em> <strong>Aboot Projects</strong>' description = 'A <script>alert("super reasonable")</script> child' res = app.post_json_api(url, { 'data': [{ 'type': 'nodes', 'attributes': { 'title': title, 'description': description, 'category': 'project', 'public': True } }] }, auth=user.auth, bulk=True) child_id = res.json['data'][0]['id'] assert res.status_code == 201 url = '/{}nodes/{}/'.format(API_BASE, child_id) res = app.get(url, auth=user.auth) assert res.json['data']['attributes']['title'] == strip_html(title) assert res.json['data']['attributes']['description'] == strip_html(description) assert res.json['data']['attributes']['category'] == 'project' project.reload() child_id = res.json['data']['id'] assert child_id == project.nodes[0]._id assert AbstractNode.load(child_id).logs.latest().action == NodeLog.PROJECT_CREATED
def test_bulk_creates_children_and_sanitizes_html_logged_in_owner(self): title = '<em>Cool</em> <strong>Project</strong>' description = 'An <script>alert("even cooler")</script> child' res = self.app.post_json_api(self.url, { 'data': [{ 'type': 'nodes', 'attributes': { 'title': title, 'description': description, 'category': 'project', 'public': True } }] }, auth=self.user.auth, bulk=True) child_id = res.json['data'][0]['id'] assert_equal(res.status_code, 201) url = '/{}nodes/{}/'.format(API_BASE, child_id) res = self.app.get(url, auth=self.user.auth) assert_equal(res.json['data']['attributes']['title'], strip_html(title)) assert_equal(res.json['data']['attributes']['description'], strip_html(description)) assert_equal(res.json['data']['attributes']['category'], 'project') self.project.reload() child_id = res.json['data']['id'] assert_equal(child_id, self.project.nodes[0]._id) assert_equal(Node.load(child_id).logs[0].action, NodeLog.PROJECT_CREATED)
def new_node(category, title, user, description=None, parent=None): """Create a new project or component. :param str category: Node category :param str title: Node title :param User user: User object :param str description: Node description :param Node project: Optional parent object :return Node: Created node """ category = category title = strip_html(title.strip()) if description: description = strip_html(description.strip()) node = Node(title=title, category=category, creator=user, description=description, parent=parent) node.save() return node
def project_new_post(auth, **kwargs): user = auth.user data = request.get_json() title = strip_html(data.get("title")) title = title.strip() category = data.get("category", "project") template = data.get("template") description = strip_html(data.get("description")) new_project = {} if template: original_node = Node.load(template) changes = {"title": title, "category": category, "template_node": original_node} if description: changes["description"] = description project = original_node.use_as_template(auth=auth, changes={template: changes}) else: try: project = new_node(category, title, user, description) except ValidationValueError as e: raise HTTPError(http.BAD_REQUEST, data=dict(message_long=e.message)) new_project = _view_project(project, auth) return {"projectUrl": project.url, "newNode": new_project["node"] if new_project else None}, http.CREATED
def project_new_post(auth, **kwargs): user = auth.user title = strip_html(request.json.get('title')) template = request.json.get('template') description = strip_html(request.json.get('description')) title = title.strip() if not title or len(title) > 200: raise HTTPError(http.BAD_REQUEST) if template: original_node = Node.load(template) changes = { 'title': title } if description: changes['description'] = description project = original_node.use_as_template( auth=auth, changes={ template: changes }) else: project = new_node('project', title, user, description) return { 'projectUrl': project.url }, http.CREATED
def new_node(category, title, user, description='', parent=None): """Create a new project or component. :param str category: Node category :param str title: Node title :param User user: User object :param str description: Node description :param Node project: Optional parent object :return Node: Created node """ # We use apps.get_model rather than import .model.Node # because we want the concrete Node class, not AbstractNode Node = apps.get_model('osf.Node') category = category title = strip_html(title.strip()) if description: description = strip_html(description.strip()) node = Node(title=title, category=category, creator=user, description=description, parent=parent) node.save() return node
def test_bulk_creates_children_and_sanitizes_html_logged_in_owner( self, app, user, project, url): title = '<em>Reasoning</em> <strong>Aboot Projects</strong>' description = 'A <script>alert("super reasonable")</script> child' res = app.post_json_api(url, { 'data': [{ 'type': 'nodes', 'attributes': { 'title': title, 'description': description, 'category': 'project', 'public': True } }] }, auth=user.auth, bulk=True) child_id = res.json['data'][0]['id'] assert res.status_code == 201 url = '/{}nodes/{}/'.format(API_BASE, child_id) res = app.get(url, auth=user.auth) assert res.json['data']['attributes']['title'] == strip_html(title) assert res.json['data']['attributes']['description'] == strip_html( description) assert res.json['data']['attributes']['category'] == 'project' project.reload() child_id = res.json['data']['id'] assert child_id == project.nodes[0]._id assert AbstractNode.load(child_id).logs.latest( ).action == NodeLog.PROJECT_CREATED
def test_strip_html_on_non_strings_returns_original_value(self): assert_true(sanitize.strip_html(True)) assert_false(sanitize.strip_html(False)) assert_equal(sanitize.strip_html(12), 12) assert_equal(sanitize.strip_html(12.3), 12.3) dtime = datetime.datetime.now() assert_equal(sanitize.strip_html(dtime), dtime)
def test_strip_html_on_non_strings_returns_original_value(self): assert_true(sanitize.strip_html(True)) assert_false(sanitize.strip_html(False)) assert_equal(sanitize.strip_html(12), 12) assert_equal(sanitize.strip_html(12.3), 12.3) dtime = timezone.now() assert_equal(sanitize.strip_html(dtime), dtime)
def test_strip_html(self): assert_equal( sanitize.strip_html('<foo>bar</foo>'), 'bar' ) assert_equal( sanitize.strip_html(b'<foo>bar</foo>'), 'bar' )
def test_update_user_sanitizes_html_properly(self): """Post request should update resource, and any HTML in fields should be stripped""" bad_fullname = 'Malcolm <strong>X</strong>' bad_family_name = 'X <script>alert("is")</script> a cool name' res = self.app.patch_json(self.user_one_url, { 'fullname': bad_fullname, 'family_name': bad_family_name, }, auth=self.user_one.auth) assert_equal(res.status_code, 200) assert_equal(res.json['data']['fullname'], strip_html(bad_fullname)) assert_equal(res.json['data']['family_name'], strip_html(bad_family_name))
def test_update_user_sanitizes_html_properly(self): """Post request should update resource, and any HTML in fields should be stripped""" bad_fullname = 'Malcolm <strong>X</strong>' bad_family_name = 'X <script>alert("is")</script> a cool name' res = self.app.patch_json_api(self.user_one_url, { 'fullname': bad_fullname, 'family_name': bad_family_name, }, auth=self.user_one.auth) assert_equal(res.status_code, 200) assert_equal(res.json['data']['attributes']['fullname'], strip_html(bad_fullname)) assert_equal(res.json['data']['attributes']['family_name'], strip_html(bad_family_name))
def register_user(**kwargs): """Register new user account. :param-json str email1: :param-json str email2: :param-json str password: :param-json str fullName: :raises: HTTPError(http.BAD_REQUEST) if validation fails or user already exists """ # Verify email address match json_data = request.get_json() if str(json_data["email1"]).lower() != str(json_data["email2"]).lower(): raise HTTPError(http.BAD_REQUEST, data=dict(message_long="Email addresses must match.")) try: full_name = request.json["fullName"] full_name = strip_html(full_name) user = framework.auth.register_unconfirmed(request.json["email1"], request.json["password"], full_name) framework.auth.signals.user_registered.send(user) except (ValidationValueError, DuplicateEmailError): raise HTTPError( http.BAD_REQUEST, data=dict(message_long=language.ALREADY_REGISTERED.format(email=request.json["email1"])) ) if settings.CONFIRM_REGISTRATIONS_BY_EMAIL: send_confirm_email(user, email=user.username) message = language.REGISTRATION_SUCCESS.format(email=user.username) return {"message": message} else: return {"message": "You may now log in."}
def test_archive_success_escaped_file_names(self): file_tree = file_tree_factory(0, 0, 0) fake_file = file_factory(name='>and&and<') fake_file_name = strip_html(fake_file['name']) file_tree['children'] = [fake_file] node = factories.NodeFactory(creator=self.user) data = { ('q_' + fake_file_name): { 'value': fake.word(), 'extra': [{ 'sha256': fake_file['extra']['hashes']['sha256'], 'viewUrl': '/project/{0}/files/osfstorage{1}'.format( node._id, fake_file['path'] ), 'selectedFileName': fake_file_name, 'nodeId': node._id }] } } schema = generate_schema_from_data(data) draft = factories.DraftRegistrationFactory(branched_from=node, registration_schema=schema, registered_metadata=data) with test_utils.mock_archive(node, schema=schema, data=data, autocomplete=True, autoapprove=True) as registration: with mock.patch.object(BaseStorageAddon, '_get_file_tree', mock.Mock(return_value=file_tree)): job = factories.ArchiveJobFactory(initiator=registration.creator) archive_success(registration._id, job._id) registration.reload() for key, question in registration.registered_meta[schema._id].items(): assert_equal(question['extra'][0]['selectedFileName'], fake_file_name)
def new_private_link(name, user, nodes, anonymous): """Create a new private link. :param str name: private link name :param User user: User object :param list Node node: a list of node object :param bool anonymous: make link anonymous or not :return PrivateLink: Created private link """ key = str(uuid.uuid4()).replace("-", "") if name: name = strip_html(name) if name is None or not name.strip(): raise ValidationValueError('Invalid link name.') else: name = "Shared project link" private_link = PrivateLink( key=key, name=name, creator=user, nodes=nodes, anonymous=anonymous ) private_link.save() return private_link
def new_private_link(name, user, nodes, anonymous): """Create a new private link. :param str name: private link name :param User user: User object :param list Node node: a list of node object :param bool anonymous: make link anonymous or not :return PrivateLink: Created private link """ key = str(uuid.uuid4()).replace('-', '') if name: name = strip_html(name) if name is None or not name.strip(): raise ValidationValueError('Invalid link name.') else: name = 'Shared project link' private_link = PrivateLink(key=key, name=name, creator=user, nodes=nodes, anonymous=anonymous) private_link.save() return private_link
def project_new_node(auth, node, **kwargs): form = NewNodeForm(request.form) user = auth.user if form.validate(): try: new_component = new_node( title=strip_html(form.title.data), user=user, category=form.category.data, parent=node, ) except ValidationValueError as e: raise HTTPError( http.BAD_REQUEST, data=dict(message_long=e.message) ) message = ( 'Your component was created successfully. You can keep working on the component page below, ' 'or return to the <u><a href="{url}">project page</a></u>.' ).format(url=node.url) status.push_status_message(message, kind='info', trust=True) return { 'status': 'success', }, 201, None, new_component.url else: # TODO: This function doesn't seem to exist anymore? status.push_errors_to_status(form.errors) raise HTTPError(http.BAD_REQUEST, redirect_url=node.url)
def project_new_node(auth, node, **kwargs): form = NewNodeForm(request.form) user = auth.user if form.validate(): try: new_component = new_node( title=strip_html(form.title.data), user=user, category=form.category.data, parent=node, ) except ValidationValueError as e: raise HTTPError(http.BAD_REQUEST, data=dict(message_long=e.message)) message = ( 'Your component was created successfully. You can keep working on the component page below, ' 'or return to the <u><a href="{url}">project page</a></u>.' ).format(url=node.url) status.push_status_message(message, kind='info', trust=True) return { 'status': 'success', }, 201, None, new_component.url else: # TODO: This function doesn't seem to exist anymore? status.push_errors_to_status(form.errors) raise HTTPError(http.BAD_REQUEST, redirect_url=node.url)
def test_update_collection_sanitizes_html_properly(self): """Post request should update resource, and any HTML in fields should be stripped""" new_title = '<strong>Super</strong><script>alert("even cooler")</script> Cool Project' res = self.app.put_json_api(self.url, { 'data': { 'id': self.collection._id, 'type': 'collections', 'attributes': { 'title': new_title, } } }, auth=self.user.auth) assert_equal(res.status_code, 200) assert_equal(res.content_type, 'application/vnd.api+json') assert_equal(res.json['data']['attributes']['title'], strip_html(new_title)) self.collection.reload() assert_equal(self.collection.title, strip_html(new_title))
def register_user(**kwargs): """ Register new user account. HTTP Method: POST :param-json str email1: :param-json str email2: :param-json str password: :param-json str fullName: :param-json str campaign: :raises: HTTPError(http.BAD_REQUEST) if validation fails or user already exists """ # Verify that email address match. # Note: Both `landing.mako` and `register.mako` already have this check on the form. Users can not submit the form # if emails do not match. However, this check should not be removed given we may use the raw api call directly. json_data = request.get_json() if str(json_data['email1']).lower() != str(json_data['email2']).lower(): raise HTTPError(http.BAD_REQUEST, data=dict(message_long='Email addresses must match.')) # Verify that captcha is valid if settings.RECAPTCHA_SITE_KEY and not validate_recaptcha( json_data.get('g-recaptcha-response'), remote_ip=request.remote_addr): raise HTTPError(http.BAD_REQUEST, data=dict(message_long='Invalid Captcha')) try: full_name = request.json['fullName'] full_name = strip_html(full_name) campaign = json_data.get('campaign') if campaign and campaign not in campaigns.get_campaigns(): campaign = None user = framework_auth.register_unconfirmed( request.json['email1'], request.json['password'], full_name, campaign=campaign, ) framework_auth.signals.user_registered.send(user) except (ValidationValueError, DuplicateEmailError): raise HTTPError( http.BAD_REQUEST, data=dict(message_long=language.ALREADY_REGISTERED.format( email=markupsafe.escape(request.json['email1'])))) except ValidationError as e: raise HTTPError(http.BAD_REQUEST, data=dict(message_long=e.message)) if settings.CONFIRM_REGISTRATIONS_BY_EMAIL: send_confirm_email(user, email=user.username) message = language.REGISTRATION_SUCCESS.format(email=user.username) return {'message': message} else: return {'message': 'You may now log in.'}
def html_and_illegal_unicode_replace(atom_element): """ Replace an illegal for XML unicode character with nothing. This fix thanks to Matt Harper from his blog post: https://maxharp3r.wordpress.com/2008/05/15/pythons-minidom-xml-and-illegal-unicode-characters/ """ if atom_element: new_element = RE_XML_ILLEGAL_COMPILED.sub('', atom_element) return strip_html(new_element) return atom_element
def test_update_user_sanitizes_html_properly(self): """Post request should update resource, and any HTML in fields should be stripped""" bad_fullname = "Malcolm <strong>X</strong>" bad_family_name = 'X <script>alert("is")</script> a cool name' res = self.app.patch_json_api( self.user_one_url, { "data": { "id": self.user_one._id, "type": "users", "attributes": {"full_name": bad_fullname, "family_name": bad_family_name}, } }, auth=self.user_one.auth, ) assert_equal(res.status_code, 200) assert_equal(res.json["data"]["attributes"]["full_name"], strip_html(bad_fullname)) assert_equal(res.json["data"]["attributes"]["family_name"], strip_html(bad_family_name))
def test_field_content_is_sanitized_upon_submission(self): bad_text = "<a href='http://sanitized.name'>User_text</a>" cleaned_text = sanitize.strip_html(bad_text) payload = copy.deepcopy(self.sample_data) payload['data']['attributes']['name'] = bad_text res = self.app.post_json_api(self.user1_list_url, payload, auth=self.user1.auth) assert_equal(res.status_code, 201) assert_equal(res.json['data']['attributes']['name'], cleaned_text)
def project_new_post(auth, **kwargs): user = auth.user data = request.get_json() title = strip_html(data.get('title')) title = title.strip() category = data.get('category', 'project') template = data.get('template') description = strip_html(data.get('description')) new_project = {} if template: original_node = Node.load(template) changes = { 'title': title, 'category': category, 'template_node': original_node, } if description: changes['description'] = description project = original_node.use_as_template( auth=auth, changes={ template: changes, } ) else: try: project = new_node(category, title, user, description) except ValidationError as e: raise HTTPError( http.BAD_REQUEST, data=dict(message_long=e.message) ) new_project = _view_project(project, auth) return { 'projectUrl': project.url, 'newNode': new_project['node'] if new_project else None }, http.CREATED
def project_new_post(auth, **kwargs): user = auth.user data = request.get_json() title = strip_html(data.get('title')) title = title.strip() category = data.get('category', 'project') template = data.get('template') description = strip_html(data.get('description')) new_project = {} if template: original_node = Node.load(template) changes = { 'title': title, 'category': category, 'template_node': original_node, } if description: changes['description'] = description project = original_node.use_as_template( auth=auth, changes={ template: changes, } ) else: try: project = new_node(category, title, user, description) except ValidationValueError as e: raise HTTPError( http.BAD_REQUEST, data=dict(message_long=e.message) ) new_project = _view_project(project, auth) return { 'projectUrl': project.url, 'newNode': new_project['node'] if new_project else None }, http.CREATED
def test_field_content_is_sanitized_upon_submission(self, app, user, url, sample_data): bad_text = '<a href=\'http://sanitized.name\'>User_text</a>' cleaned_text = sanitize.strip_html(bad_text) payload = copy.copy(sample_data) payload['data']['attributes']['name'] = bad_text payload['data']['attributes']['description'] = bad_text res = app.post_json_api(url, payload, auth=user.auth) assert res.status_code == 201 assert res.json['data']['attributes']['name'] == cleaned_text
def deserialize_contributors(node, user_dicts, auth, validate=False): """View helper that returns a list of User objects from a list of serialized users (dicts). The users in the list may be registered or unregistered users. e.g. ``[{'id': 'abc123', 'registered': True, 'fullname': ..}, {'id': None, 'registered': False, 'fullname'...}, {'id': '123ab', 'registered': False, 'fullname': ...}] If a dict represents an unregistered user without an ID, creates a new unregistered User record. :param Node node: The node to add contributors to :param list(dict) user_dicts: List of serialized users in the format above. :param Auth auth: :param bool validate: Whether to validate and sanitize fields (if necessary) """ # Add the registered contributors contribs = [] for contrib_dict in user_dicts: fullname = contrib_dict["fullname"] visible = contrib_dict["visible"] email = contrib_dict.get("email") if validate is True: # Validate and sanitize inputs as needed. Email will raise error if invalid. # TODO Edge case bug: validation and saving are performed in same loop, so all in list # up to the invalid entry will be saved. (communicate to the user what needs to be retried) fullname = sanitize.strip_html(fullname) if not fullname: raise ValidationValueError("Full name field cannot be empty") if email: validate_email(email) # Will raise a ValidationError if email invalid if contrib_dict["id"]: contributor = User.load(contrib_dict["id"]) else: try: contributor = User.create_unregistered(fullname=fullname, email=email) contributor.save() except ValidationValueError: ## FIXME: This suppresses an exception if ID not found & new validation fails; get_user will return None contributor = get_user(email=email) # Add unclaimed record if necessary if not contributor.is_registered and node._primary_key not in contributor.unclaimed_records: contributor.add_unclaimed_record(node=node, referrer=auth.user, given_name=fullname, email=email) contributor.save() contribs.append( {"user": contributor, "visible": visible, "permissions": expand_permissions(contrib_dict.get("permission"))} ) return contribs
def test_update_project_sanitizes_html_properly(self): """Post request should update resource, and any HTML in fields should be stripped""" new_title = '<strong>Super</strong> Cool Project' new_description = 'An <script>alert("even cooler")</script> project' res = self.app.put_json_api(self.public_url, { 'data': { 'id': self.public_project._id, 'type': 'nodes', 'attributes': { 'title': new_title, 'description': new_description, 'category': self.new_category, 'public': True, } } }, auth=self.user.auth) assert_equal(res.status_code, 200) assert_equal(res.content_type, 'application/vnd.api+json') assert_equal(res.json['data']['attributes']['title'], strip_html(new_title)) assert_equal(res.json['data']['attributes']['description'], strip_html(new_description))
def test_field_content_is_sanitized_upon_submission( self, app, data_sample, user_one, url_token_list): bad_text = '<a href="http://sanitized.name">User_text</a>' cleaned_text = sanitize.strip_html(bad_text) payload = copy.deepcopy(data_sample) payload['data']['attributes']['name'] = bad_text res = app.post_json_api(url_token_list, payload, auth=user_one.auth) assert res.status_code == 201 assert res.json['data']['attributes']['name'] == cleaned_text
def test_update_user_sanitizes_html_properly( self, app, user_one, url_user_one): """Post request should update resource, and any HTML in fields should be stripped""" bad_fullname = 'Malcolm <strong>X</strong>' bad_family_name = 'X <script>alert("is")</script> a cool name' res = app.patch_json_api(url_user_one, { 'data': { 'id': user_one._id, 'type': 'users', 'attributes': { 'full_name': bad_fullname, 'family_name': bad_family_name, } } }, auth=user_one.auth) assert res.status_code == 200 assert res.json['data']['attributes']['full_name'] == strip_html( bad_fullname) assert res.json['data']['attributes']['family_name'] == strip_html( bad_family_name)
def edit_profile(**kwargs): user = kwargs['auth'].user form = request.form response_data = {'response': 'success'} if form.get('name') == 'fullname' and form.get('value', '').strip(): user.fullname = strip_html(form['value']) user.save() response_data['name'] = user.fullname return response_data
def test_update_user_sanitizes_html_properly(self, app, user_one, url_user_one): """Post request should update resource, and any HTML in fields should be stripped""" bad_fullname = 'Malcolm <strong>X</strong>' bad_family_name = 'X <script>alert("is")</script> a cool name' res = app.patch_json_api(url_user_one, { 'data': { 'id': user_one._id, 'type': 'users', 'attributes': { 'full_name': bad_fullname, 'family_name': bad_family_name, } } }, auth=user_one.auth) assert res.status_code == 200 assert res.json['data']['attributes']['full_name'] == strip_html( bad_fullname) assert res.json['data']['attributes']['family_name'] == strip_html( bad_family_name)
def test_field_content_is_sanitized_upon_submission( self, app, user, url, sample_data): bad_text = '<a href=\'http://sanitized.name\'>User_text</a>' cleaned_text = sanitize.strip_html(bad_text) payload = copy.copy(sample_data) payload['data']['attributes']['name'] = bad_text payload['data']['attributes']['description'] = bad_text res = app.post_json_api(url, payload, auth=user.auth) assert res.status_code == 201 assert res.json['data']['attributes']['name'] == cleaned_text
def register_user(**kwargs): """ Register new user account. HTTP Method: POST :param-json str email1: :param-json str email2: :param-json str password: :param-json str fullName: :param-json str campaign: :raises: HTTPError(http.BAD_REQUEST) if validation fails or user already exists """ # Verify email address match json_data = request.get_json() if str(json_data['email1']).lower() != str(json_data['email2']).lower(): raise HTTPError( http.BAD_REQUEST, data=dict(message_long='Email addresses must match.') ) try: full_name = request.json['fullName'] full_name = strip_html(full_name) campaign = json_data.get('campaign') if campaign and campaign not in campaigns.CAMPAIGNS: campaign = None user = framework_auth.register_unconfirmed( request.json['email1'], request.json['password'], full_name, campaign=campaign, ) framework_auth.signals.user_registered.send(user) except (ValidationValueError, DuplicateEmailError): raise HTTPError( http.BAD_REQUEST, data=dict( message_long=language.ALREADY_REGISTERED.format( email=markupsafe.escape(request.json['email1']) ) ) ) if settings.CONFIRM_REGISTRATIONS_BY_EMAIL: send_confirm_email(user, email=user.username) message = language.REGISTRATION_SUCCESS.format(email=user.username) return {'message': message} else: return {'message': 'You may now log in.'}
def show_diff(seqm): """Unify operations between two compared strings seqm is a difflib.SequenceMatcher instance whose a & b are strings""" output = [] insert_el = '<span style="background:#4AA02C; font-size:1.5em; ">' ins_el_close = '</span>' del_el = '<span style="background:#D16587; font-size:1.5em;">' del_el_close = '</span>' for opcode, a0, a1, b0, b1 in seqm.get_opcodes(): content_a = strip_html(seqm.a[a0:a1]) content_b = strip_html(seqm.b[b0:b1]) if opcode == 'equal': output.append(content_a) elif opcode == 'insert': output.append(insert_el + content_b + ins_el_close) elif opcode == 'delete': output.append(del_el + content_a + del_el_close) elif opcode == 'replace': output.append(del_el + content_a + del_el_close + insert_el + content_b + ins_el_close) else: raise RuntimeError("unexpected opcode") return ''.join(output)
def show_diff(seqm): """Unify operations between two compared strings seqm is a difflib.SequenceMatcher instance whose a & b are strings""" output = [] insert_el = '<span style="background:#4AA02C; font-size:1.5em; ">' ins_el_close = '</span>' del_el = '<span style="background:#D16587; font-size:1.5em;">' del_el_close = '</span>' for opcode, a0, a1, b0, b1 in seqm.get_opcodes(): content_a = strip_html(seqm.a[a0:a1]) content_b = strip_html(seqm.b[b0:b1]) if opcode == 'equal': output.append(content_a) elif opcode == 'insert': output.append(insert_el + content_b + ins_el_close) elif opcode == 'delete': output.append(del_el + content_a + del_el_close) elif opcode == 'replace': output.append(del_el + content_a + del_el_close + insert_el + content_b + ins_el_close) else: raise RuntimeError('unexpected opcode') return ''.join(output)
def edit_profile(**kwargs): # NOTE: This method is deprecated. Use update_user instead. # TODO: Remove this view user = kwargs['auth'].user form = request.form ret = {'response': 'success'} if form.get('name') == 'fullname' and form.get('value', '').strip(): user.fullname = strip_html(form['value']).strip() user.save() ret['name'] = user.fullname return ret
def edit_profile(**kwargs): # NOTE: This method is deprecated. Use update_user instead. # TODO: Remove this view user = kwargs["auth"].user form = request.form ret = {"response": "success"} if form.get("name") == "fullname" and form.get("value", "").strip(): user.fullname = strip_html(form["value"]).strip() user.save() ret["name"] = user.fullname return ret
def edit_node(auth, node, **kwargs): post_data = request.json edited_field = post_data.get("name") value = strip_html(post_data.get("value", "")) if edited_field == "title": try: node.set_title(value, auth=auth) except ValidationValueError as e: raise HTTPError(http.BAD_REQUEST, data=dict(message_long=e.message)) elif edited_field == "description": node.set_description(value, auth=auth) node.save() return {"status": "success"}
def project_new_node(auth, node, **kwargs): form = NewNodeForm(request.form) user = auth.user if form.validate(): try: new_component = new_node( title=strip_html(form.title.data), user=user, category=form.category.data, parent=node, ) except ValidationError as e: raise HTTPError(http.BAD_REQUEST, data=dict(message_long=e.message)) redirect_url = node.url message = ( 'Your component was created successfully. You can keep working on the project page below, ' 'or go to the new <u><a href={component_url}>component</a></u>.' ).format(component_url=new_component.url) if form.inherit_contributors.data and node.has_permission(user, WRITE): for contributor in node.contributors: perm = CREATOR_PERMISSIONS if contributor._id == user._id else node.get_permissions( contributor) if contributor._id == user._id and not contributor.is_registered: new_component.add_unregistered_contributor( fullname=contributor.fullname, email=contributor.email, permissions=perm, auth=auth, existing_user=contributor) else: new_component.add_contributor(contributor, permissions=perm, auth=auth) new_component.save() redirect_url = new_component.url + 'contributors/' message = ( 'Your component was created successfully. You can edit the contributor permissions below, ' 'work on your <u><a href={component_url}>component</a></u> or return to the <u> ' '<a href="{project_url}">project page</a></u>.').format( component_url=new_component.url, project_url=node.url) status.push_status_message(message, kind='info', trust=True) return { 'status': 'success', }, 201, None, redirect_url else: # TODO: This function doesn't seem to exist anymore? status.push_errors_to_status(form.errors) raise HTTPError(http.BAD_REQUEST, redirect_url=node.url)
def edit_node(auth, node, **kwargs): post_data = request.json edited_field = post_data.get('name') value = strip_html(post_data.get('value', '')) if edited_field == 'title': try: node.set_title(value, auth=auth) except ValidationValueError: raise HTTPError(http.BAD_REQUEST, data=dict(message_long='Title cannot be blank.')) elif edited_field == 'description': node.set_description(value, auth=auth) node.save() return {'status': 'success'}
def register_user(**kwargs): """Register new user account. :param-json str email1: :param-json str email2: :param-json str password: :param-json str fullName: :param-json str campaign: :raises: HTTPError(http.BAD_REQUEST) if validation fails or user already exists """ # Verify email address match json_data = request.get_json() if str(json_data['email1']).lower() != str(json_data['email2']).lower(): raise HTTPError( http.BAD_REQUEST, data=dict(message_long='Email addresses must match.') ) try: full_name = request.json['fullName'] full_name = strip_html(full_name) campaign = json_data.get('campaign') if campaign and campaign not in campaigns.CAMPAIGNS: campaign = None user = framework.auth.register_unconfirmed( request.json['email1'], request.json['password'], full_name, campaign=campaign, ) framework.auth.signals.user_registered.send(user) except (ValidationValueError, DuplicateEmailError): raise HTTPError( http.BAD_REQUEST, data=dict( message_long=language.ALREADY_REGISTERED.format( email=request.json['email1'] ) ) ) if settings.CONFIRM_REGISTRATIONS_BY_EMAIL: send_confirm_email(user, email=user.username) message = language.REGISTRATION_SUCCESS.format(email=user.username) return {'message': message} else: return {'message': 'You may now log in.'}
def project_new_post(auth, **kwargs): user = auth.user data = request.get_json() title = strip_html(data.get('title')) title = title.strip() category = data.get('category', 'project') template = data.get('template') description = strip_html(data.get('description')) if not title or len(title) > 200: raise HTTPError(http.BAD_REQUEST) if template: original_node = Node.load(template) changes = { 'title': title, 'category': category, 'template_node': original_node, } if description: changes['description'] = description project = original_node.use_as_template( auth=auth, changes={ template: changes, } ) else: project = new_node(category, title, user, description) return { 'projectUrl': project.url }, http.CREATED
def new_folder(title, user): """Create a new folder project. :param str title: Node title :param User user: User object :return Node: Created node """ title = strip_html(title.strip()) node = Node(title=title, creator=user, category='project', is_folder=True) node.save() return node
def test_update_project_sanitizes_html_properly(self): """Post request should update resource, and any HTML in fields should be stripped""" new_title = "<strong>Super</strong> Cool Project" new_description = 'An <script>alert("even cooler")</script> project' res = self.app.put_json_api( self.public_url, { "data": { "id": self.public_project._id, "type": "nodes", "attributes": { "title": new_title, "description": new_description, "category": self.new_category, "public": True, }, } }, auth=self.user.auth, ) assert_equal(res.status_code, 200) assert_equal(res.content_type, "application/vnd.api+json") assert_equal(res.json["data"]["attributes"]["title"], strip_html(new_title)) assert_equal(res.json["data"]["attributes"]["description"], strip_html(new_description))
def validate_title(value): """Validator for Node#title. Makes sure that the value exists and is not above 200 characters. """ if value is None or not value.strip(): raise ValidationValueError('Title cannot be blank.') value = strip_html(value) if value is None or not value.strip(): raise ValidationValueError('Invalid title.') if len(value) > 200: raise ValidationValueError('Title cannot exceed 200 characters.') return True
def add_folder(**kwargs): auth = kwargs['auth'] user = auth.user title = strip_html(request.json.get('title')) node_id = request.json.get('node_id') node = Node.load(node_id) if node.is_deleted or node.is_registration or not node.is_folder: raise HTTPError(http.BAD_REQUEST) folder = new_folder(title, user) folders = [folder] try: _add_pointers(node, folders, auth) except ValueError: raise HTTPError(http.BAD_REQUEST) return {}, 201, None
def folder_new_post(auth, node, **kwargs): user = auth.user title = request.json.get('title') if not node.is_folder: raise HTTPError(http.BAD_REQUEST) folder = new_folder(strip_html(title), user) folders = [folder] try: _add_pointers(node, folders, auth) except ValueError: raise HTTPError(http.BAD_REQUEST) return { 'projectUrl': '/dashboard/', }, http.CREATED
def add_folder(auth, **kwargs): data = request.get_json() node_id = data.get('node_id') node = get_or_http_error(Node, node_id) user = auth.user title = strip_html(data.get('title')) if not node.is_folder: raise HTTPError(http.BAD_REQUEST) folder = new_folder(title, user) folders = [folder] try: _add_pointers(node, folders, auth) except ValueError: raise HTTPError(http.BAD_REQUEST) return {}, 201, None