Ticket: Create / Update Comments UI issue

My code passes the test cases:

pytest -m create_update_comments
============================= test session starts ==============================
platform linux – Python 3.5.2, pytest-4.1.0, py-1.7.0, pluggy-0.8.0
rootdir: /home/qolsys/Desktop/Courses/MongoDB/mflix-python, inifile:
plugins: flask-0.14.0
collected 43 items / 39 deselected

tests/test_create_update_comments.py … [100%]

=================== 4 passed, 39 deselected in 13.17 seconds ===================

But in the UI, it always show Create/Update Comments: Was able to update a comment that wasn’t owned
I have checked my code but couldn’t find any issues with it. I was able to get the validation code for delete comments in the similar way of code writing. I have also used the ObjectId() for respective ids in my code.

Here is my code:

def add_comment(movie_id, user, comment, date):
“”"
Inserts a comment into the comments collection, with the following fields:

- "name"
- "email"
- "movie_id"
- "text"
- "date"

Name and email must be retrieved from the "user" object.
"""
# TODO: Create/Update Comments
# Construct the comment document to be inserted into MongoDB.
comment_doc = {"name": user.name, "email": user.email, "movie_id": ObjectId(movie_id), "text": comment, "date": date}
return db.comments.insert_one(comment_doc)

def update_comment(comment_id, user_email, text, date):
“”"
Updates the comment in the comment collection. Queries for the comment
based by both comment _id field as well as the email field to doubly ensure
the user has permission to edit this comment.
“”"
# TODO: Create/Update Comments
# Use the user_email and comment_id to select the proper comment, then
# update the “text” and “date” of the selected comment.
response = db.comments.update_one({“email”: user_email, “_id”: ObjectId(comment_id)}, {"$set": {“text”: text, “date”: date}})
return response

def delete_comment(comment_id, user_email):
“”"
Given a user’s email and a comment ID, deletes a comment from the comments
collection
“”"

"""
Ticket: Delete Comments

Match the comment_id and user_email with the correct fields, to make sure
this user has permission to delete this comment, and then delete it.
"""

# TODO: Delete Comments
# Use the user_email and comment_id to delete the proper comment.
response = db.comments.delete_one(
    {"email": user_email, "_id": ObjectId(comment_id)}
)
return response
2 Likes

Same issue with this:

Hi there,

same problem here. The test pytest -m create_update_comments is green but the app’s status view shows a red “Create/Update Comments: Was able to update a comment that wasn’t owned”.

In both cases, however, the value of response.modified_count as well as response.raw_result.get('nModified') is 0 for the test “test_do_not_update_comment_if_is_not_owner”. Just as expected. (Printed it to the console.)

So why does the status page show the test as failed?

Would be great if the instructors could help? Thanks a lot!

1 Like

I have the same issue. I am still working on it. I’ll let you know if I make any progress.

Does pytest -m create_update_comments still also succeed?

1 Like

Hi Steeve,

you’re right: now the test test_do_not_update_comment_if_is_not_owner fails because – well, the intended exception gets thrown. Yippee! :beer:

The fix, though, should not be totally silly because it addresses the actual Rest API’s requirements as they are now.

But anyway: the problem is located. Maybe, the instructors will adjust either the test or the Rest API endpoint api_update_comment.

I have the same problem. The solution from Andreas_04985 did not work for me. Now I just get “Unable to update comment” as an error.

I also have a similar problem with delete comment where I get “Deletion was performed but unsuccessful”.
I’m pretty sure the code is right.

def update_comment(comment_id, user_email, text, date):
“”"
Updates the comment in the comment collection. Queries for the comment
based by both comment _id field as well as the email field to doubly ensure
the user has permission to edit this comment.
“”"
# TODO: Create/Update Comments
# Use the user_email and comment_id to select the proper comment, then
# update the “text” and “date” of the selected comment.
response = db.comments.update_one(
{"_id": ObjectId(comment_id), “email”: user_email},
{"$set": {“text”: text, “date”: date}}
)

return response

def delete_comment(comment_id, user_email):
“”"
Given a user’s email and a comment ID, deletes a comment from the comments
collection
“”"

"""
Ticket: Delete Comments

Match the comment_id and user_email with the correct fields, to make sure
this user has permission to delete this comment, and then delete it.
"""

# TODO: Delete Comments
# Use the user_email and comment_id to delete the proper comment.
response = db.comments.delete_one(
    {"_id": ObjectId(comment_id), "email": user_email}
)

return response

Anyone else have any more ideas? It’s a shame to miss 2 tickets because of this…

Hi there,

Here’s a modified solution that let’s the pytest and the tests on the status view page pass.

I’ve now decided to edit the method api_update_comment in “mflix/api/movies.py” mentioned above:

@movies_api_v1.route('/comment', methods=["PUT"])
@jwt_required
def api_update_comment():
    claims = get_jwt_claims()
    user_email = User.from_claims(claims).email
    post_data = request.get_json()
    try:
        comment_id = expect(post_data.get('comment_id'), str, 'comment_id')
        updated_comment = expect(post_data.get(
            'updated_comment'), str, 'updated_comment')
        movie_id = expect(post_data.get('movie_id'), str, 'movie_id')
        
        # start: my edit
        # added by myself to fix issue with incompatible test “test_do_not_update_comment_if_is_not_owner”
        # see: <https://www.mongodb.com/community/forums/t/ticket-create-update-comments-ui-issue/9818/9>
        # was: update_comment(comment_id, user_email, updated_comment, datetime.now())
        response = update_comment(comment_id, user_email, updated_comment, datetime.now())
        if response.raw_result.get('nModified') == 0:
          raise Exception('Nope!')
        # end: my edit

        updated_comments = get_movie(movie_id).get('comments')
        return jsonify({"comments": updated_comments}), 200
    except Exception as e:
        return jsonify({'error': str(e)}), 400

Our db method can then be as straightforward as before:

def update_comment(comment_id, user_email, text, date):
    response = db.comments.update_one({
        "_id": ObjectId(comment_id),
        "email": user_email
    }, {
        "$set": {"text": text, "date": date}
    })
    return response

Of course, we are not supposed to edit the build code but I think in this case it’s an acceptable temporary fix. It does not modify the test nor the Rest API’s behaviour.

(It’s not best practice because the method movies.api_update_comment should not know anything about database stuff – but as mentioned in my longer post above the test and the API method are not compatible as of now and as far as I can see.)

So to proceed with the course without “cheating” this monkey fix should be acceptable. Happy learning and coding! :coffee:

5 Likes

Thanks @Andreas_04985 for sharing your solution.

Personally, I chose to modify the unit test so that I catch the exception that is now raised by update_comment(). The assert in the except…: is there to make sure I mess around only the exception I raised in update_comment(). This way all other exceptions still make the unit test to fail.

      try:
          # Existing code of test_do_not_update_comment_if_is_not_owner() left unchanged
      except Exception as x_ :
          assert str( x_ ) == "response.modified_count == 0"
2 Likes

Hi @steevej-1495
I like your solution! It does not need the api_update_comment method (in “mflix/api/movies.py”) to know anything about the database internals. I guess that’s a better solution than mine. … Problem located, explained, and solved I’d say!

I would say problem patched. I think mongodb team should issue a real fix either in the API or in the test. But for now I am happy with what we have. At least I would appreciate a comment from the teaching team on the issue. Just in case we missed something important.

Hi @steevej-1495,

Clearly the unit test needs to address an edge case caused by your implementation.
The integration test is correctly implemented but the unittest is missing a case.
We will post a fix to this soon.

Thanks for flagging.

N.

1 Like

Thanks Steve for your solution. I’ve been struggling with this issue for a long time now.
All my tests pass now.

Modifying movies.py works and now the web page gives the code correctly. Thanks, @steevej-1495 !!!

I want to share your thanks with @Andreas_04985 as he has put us on the right path.

i have an issue here guys. i have done the necessary things for create and update comments but im still failing


any help please

The problem seems to be about getMovie() which does not return the comments of a movie correctly.

i dont know how to get pass that

def get_user(email):
"""
Given an email, returns a document from the `users` collection.
"""
# TODO: User Management
# Retrieve the user document corresponding with the user's email.
return db.users.find_one({ "email": email })

get user function works fine

You have to go back to the Get Comments ticket and fix your code.