Fixed updating username in settings view
The timestamps used by the 'last viewed' property of the video progress feature were converted to strings when sending to the frontend, but never changed back to timestamps when PUTting via the SDK. I solved it by not PUTing the user at all, but using PATCH to set the username instead.
This commit is contained in:
parent
23f8c1a446
commit
0f0a4be412
@ -61,6 +61,9 @@ def _update_search_user_changed_role(sender, user: dict):
|
||||
|
||||
def setup_app(app, api_prefix):
|
||||
from pillar.api import service
|
||||
from . import patch
|
||||
|
||||
patch.setup_app(app, url_prefix=api_prefix)
|
||||
|
||||
app.on_pre_GET_users += hooks.check_user_access
|
||||
app.on_post_GET_users += hooks.post_GET_user
|
||||
|
45
pillar/api/users/patch.py
Normal file
45
pillar/api/users/patch.py
Normal file
@ -0,0 +1,45 @@
|
||||
"""User patching support."""
|
||||
|
||||
import logging
|
||||
|
||||
import bson
|
||||
from flask import Blueprint
|
||||
import werkzeug.exceptions as wz_exceptions
|
||||
|
||||
from pillar import current_app
|
||||
from pillar.auth import current_user
|
||||
from pillar.api.utils import authorization, jsonify, remove_private_keys
|
||||
from pillar.api import patch_handler
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
patch_api_blueprint = Blueprint('users.patch', __name__)
|
||||
|
||||
|
||||
class UserPatchHandler(patch_handler.AbstractPatchHandler):
|
||||
item_name = 'user'
|
||||
|
||||
@authorization.require_login()
|
||||
def patch_set_username(self, user_id: bson.ObjectId, patch: dict):
|
||||
"""Updates a user's username."""
|
||||
if user_id != current_user.user_id:
|
||||
log.info('User %s tried to change username of user %s',
|
||||
current_user.user_id, user_id)
|
||||
raise wz_exceptions.Forbidden('You may only change your own username')
|
||||
|
||||
new_username = patch['username']
|
||||
log.info('User %s uses PATCH to set username to %r', current_user.user_id, new_username)
|
||||
|
||||
users_coll = current_app.db('users')
|
||||
db_user = users_coll.find_one({'_id': user_id})
|
||||
db_user['username'] = new_username
|
||||
|
||||
# Save via Eve to check the schema and trigger update hooks.
|
||||
response, _, _, status = current_app.put_internal(
|
||||
'users', remove_private_keys(db_user), _id=user_id)
|
||||
|
||||
return jsonify(response), status
|
||||
|
||||
|
||||
def setup_app(app, url_prefix):
|
||||
UserPatchHandler(patch_api_blueprint)
|
||||
app.register_api_blueprint(patch_api_blueprint, url_prefix=url_prefix)
|
@ -11,6 +11,8 @@ import flask_login
|
||||
import jinja2.filters
|
||||
import jinja2.utils
|
||||
import werkzeug.exceptions as wz_exceptions
|
||||
from werkzeug.local import LocalProxy
|
||||
|
||||
import pillarsdk
|
||||
|
||||
import pillar.api.utils
|
||||
@ -225,6 +227,8 @@ def user_to_dict(user: auth.UserClass) -> dict:
|
||||
|
||||
|
||||
def do_json(some_object) -> str:
|
||||
if isinstance(some_object, LocalProxy):
|
||||
return do_json(some_object._get_current_object())
|
||||
if isinstance(some_object, pillarsdk.Resource):
|
||||
some_object = some_object.to_dict()
|
||||
if isinstance(some_object, auth.UserClass):
|
||||
|
@ -7,6 +7,7 @@ from flask_login import login_required, current_user
|
||||
from werkzeug.exceptions import abort
|
||||
|
||||
from pillar import current_app
|
||||
from pillar.auth import current_user
|
||||
from pillar.web import system_util
|
||||
from pillar.web.users import forms
|
||||
from pillarsdk import User, exceptions as sdk_exceptions
|
||||
@ -29,11 +30,12 @@ def profile():
|
||||
|
||||
if form.validate_on_submit():
|
||||
try:
|
||||
user.username = form.username.data
|
||||
user.update(api=api)
|
||||
response = user.set_username(form.username.data, api=api)
|
||||
log.info('updated username of %s: %s', current_user, response)
|
||||
flash("Profile updated", 'success')
|
||||
except sdk_exceptions.ResourceInvalid as e:
|
||||
message = json.loads(e.content)
|
||||
except sdk_exceptions.ResourceInvalid as ex:
|
||||
log.warning('unable to set username %s to %r: %s', current_user, form.username.data, ex)
|
||||
message = json.loads(ex.content)
|
||||
flash(message)
|
||||
|
||||
blender_id_endpoint = current_app.config['BLENDER_ID_ENDPOINT']
|
||||
|
37
tests/test_web/test_user_settings.py
Normal file
37
tests/test_web/test_user_settings.py
Normal file
@ -0,0 +1,37 @@
|
||||
import flask
|
||||
import flask_login
|
||||
from pillar.tests import AbstractPillarTest
|
||||
|
||||
|
||||
class UsernameTest(AbstractPillarTest):
|
||||
def setUp(self, **kwargs) -> None:
|
||||
super().setUp(**kwargs)
|
||||
self.user_id = self.create_user()
|
||||
|
||||
def test_update_via_web(self) -> None:
|
||||
from pillar.auth import current_user
|
||||
import pillar.web.settings.routes
|
||||
|
||||
with self.app.app_context():
|
||||
url = flask.url_for('settings.profile')
|
||||
|
||||
with self.app.test_request_context(
|
||||
path=url,
|
||||
data={'username': 'je.moeder'},
|
||||
method='POST',
|
||||
):
|
||||
self.login_api_as(self.user_id)
|
||||
flask_login.login_user(current_user)
|
||||
pillar.web.settings.routes.profile()
|
||||
|
||||
db_user = self.fetch_user_from_db(self.user_id)
|
||||
self.assertEqual('je.moeder', db_user['username'])
|
||||
|
||||
def test_update_via_patch(self) -> None:
|
||||
self.create_valid_auth_token(self.user_id, 'user-token')
|
||||
self.patch(f'/api/users/{self.user_id}',
|
||||
json={'op': 'set-username', 'username': 'je.moeder'},
|
||||
auth_token='user-token')
|
||||
|
||||
db_user = self.fetch_user_from_db(self.user_id)
|
||||
self.assertEqual('je.moeder', db_user['username'])
|
Loading…
x
Reference in New Issue
Block a user