Rename users when they log in with a new preferred_username

This commit is contained in:
Paul Bienkowski 2022-09-13 08:56:12 +02:00
parent 5cfc8aae39
commit 0ab5a87c77
2 changed files with 45 additions and 9 deletions

View file

@ -3,7 +3,7 @@ from contextvars import ContextVar
from contextlib import asynccontextmanager from contextlib import asynccontextmanager
from datetime import datetime from datetime import datetime
import os import os
from os.path import join, dirname from os.path import exists, join, dirname
from json import loads from json import loads
import re import re
import math import math
@ -12,6 +12,7 @@ import random
import string import string
import secrets import secrets
from slugify import slugify from slugify import slugify
import logging
from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.ext.asyncio import AsyncSession
@ -37,6 +38,8 @@ from sqlalchemy import (
from sqlalchemy.dialects.postgresql import HSTORE, UUID from sqlalchemy.dialects.postgresql import HSTORE, UUID
log = logging.getLogger(__name__)
Base = declarative_base() Base = declarative_base()
@ -377,6 +380,29 @@ class User(Base):
"image": self.image, "image": self.image,
} }
async def rename(self, config, new_name):
old_name = self.username
renames = [
(join(basedir, old_name), join(basedir, new_name))
for basedir in [config.PROCESSING_OUTPUT_DIR, config.TRACKS_DIR]
]
for src, dst in renames:
if exists(dst):
raise FileExistsError(
f"cannot move {src!r} to {dst!r}, destination exists"
)
for src, dst in renames:
if not exists(src):
log.debug("Rename user %s: Not moving %s, not found", self.id, src)
else:
log.info("Rename user %s: Moving %s to %s", self.id, src, dst)
os.rename(src, dst)
self.username = new_name
class Comment(Base): class Comment(Base):
__tablename__ = "comment" __tablename__ = "comment"
@ -403,7 +429,10 @@ class Comment(Base):
Comment.author = relationship("User", back_populates="authored_comments") Comment.author = relationship("User", back_populates="authored_comments")
User.authored_comments = relationship( User.authored_comments = relationship(
"Comment", order_by=Comment.created_at, back_populates="author", passive_deletes=True "Comment",
order_by=Comment.created_at,
back_populates="author",
passive_deletes=True,
) )
Track.author = relationship("User", back_populates="authored_tracks") Track.author = relationship("User", back_populates="authored_tracks")
@ -418,7 +447,10 @@ Track.comments = relationship(
OvertakingEvent.track = relationship("Track", back_populates="overtaking_events") OvertakingEvent.track = relationship("Track", back_populates="overtaking_events")
Track.overtaking_events = relationship( Track.overtaking_events = relationship(
"OvertakingEvent", order_by=OvertakingEvent.time, back_populates="track", passive_deletes=True "OvertakingEvent",
order_by=OvertakingEvent.time,
back_populates="track",
passive_deletes=True,
) )

View file

@ -128,16 +128,20 @@ async def login_redirect(req):
user = User(sub=sub, username=preferred_username, email=email) user = User(sub=sub, username=preferred_username, email=email)
req.ctx.db.add(user) req.ctx.db.add(user)
else: else:
log.info("Logged in known user (id: %s, sub: %s).", user.id, user.sub) log.info(
"Logged in known user (id: %s, sub: %s, %s).",
user.id,
user.sub,
preferred_username,
)
if email != user.email: if email != user.email:
log.debug("Updating user (id: %s) email from auth system.", user.id) log.debug("Updating user (id: %s) email from auth system.", user.id)
user.email = email user.email = email
# TODO: re-add username change when we can safely rename users if preferred_username != user.username:
# if preferred_username != user.username: log.debug("Updating user (id: %s) username from auth system.", user.id)
# log.debug("Updating user (id: %s) username from auth system.", user.id) await user.rename(req.app.config, preferred_username)
# user.username = preferred_username
await req.ctx.db.commit() await req.ctx.db.commit()
@ -156,4 +160,4 @@ async def logout(req):
auth_req = client.construct_EndSessionRequest(state=session["state"]) auth_req = client.construct_EndSessionRequest(state=session["state"])
logout_url = auth_req.request(client.end_session_endpoint) logout_url = auth_req.request(client.end_session_endpoint)
return redirect(logout_url+f"&redirect_uri={req.ctx.api_url}/logout") return redirect(logout_url + f"&redirect_uri={req.ctx.api_url}/logout")