add better member name validation, add debug user create endpoint

This commit is contained in:
sam 2024-03-22 21:37:09 +01:00
parent 1bd07dd771
commit afadffbaac
3 changed files with 66 additions and 14 deletions

View file

@ -8,9 +8,7 @@ from foxnouns.db import Member
from foxnouns.db.aio import async_session from foxnouns.db.aio import async_session
from foxnouns.db.util import user_from_ref, is_self from foxnouns.db.util import user_from_ref, is_self
from foxnouns.exceptions import NotFoundError, ErrorCode from foxnouns.exceptions import NotFoundError, ErrorCode
from foxnouns.models import BasePatchModel from foxnouns.models.member import FullMemberModel, MemberPatchModel
from foxnouns.models.member import FullMemberModel
from foxnouns.models.fields import ProfileField, FieldEntry, PronounEntry
from foxnouns.settings import BASE_DOMAIN from foxnouns.settings import BASE_DOMAIN
bp = Blueprint("members_v2", __name__) bp = Blueprint("members_v2", __name__)
@ -27,20 +25,19 @@ async def get_members(user_ref: str):
return [FullMemberModel.model_validate(m) for m in user.members] return [FullMemberModel.model_validate(m) for m in user.members]
class MemberPostData(BasePatchModel): class MemberCreateModel(MemberPatchModel):
name: str = Field(min_length=1, max_length=100) # TODO: validate member names more name: str = Field(
bio: str | None = Field(max_length=1024, default=None) min_length=1,
max_length=100,
names: list[FieldEntry] = Field(default=[]) pattern=r"^[^@\?!#\/\\\[\]\"\{\}'$%&()+<=>^|~`,\*]{1,100}$",
pronouns: list[PronounEntry] = Field(default=[]) )
fields: list[ProfileField] = Field(default=[])
@bp.post("/api/v2/members", host=BASE_DOMAIN) @bp.post("/api/v2/members", host=BASE_DOMAIN)
@require_auth(scope="member.create") @require_auth(scope="member.create")
@validate_request(MemberPostData) @validate_request(MemberCreateModel)
@validate_response(FullMemberModel, 200) @validate_response(FullMemberModel, 200)
async def create_member(data: MemberPostData): async def create_member(data: MemberCreateModel):
async with async_session() as session: async with async_session() as session:
member = Member( member = Member(
user_id=g.user.id, user_id=g.user.id,

View file

@ -6,7 +6,8 @@ from sqlalchemy import select
from foxnouns.auth import require_auth from foxnouns.auth import require_auth
from foxnouns.db import User from foxnouns.db import User
from foxnouns.db.aio import async_session from foxnouns.db.aio import async_session
from foxnouns.db.util import user_from_ref, is_self from foxnouns.db.snowflake import Snowflake
from foxnouns.db.util import user_from_ref, is_self, create_token, generate_token
from foxnouns.exceptions import NotFoundError, ErrorCode from foxnouns.exceptions import NotFoundError, ErrorCode
from foxnouns.models import BasePatchModel from foxnouns.models import BasePatchModel
from foxnouns.models.user import UserModel, SelfUserModel, check_username from foxnouns.models.user import UserModel, SelfUserModel, check_username
@ -48,6 +49,8 @@ class EditUserRequest(BasePatchModel):
@validate_request(EditUserRequest) @validate_request(EditUserRequest)
@validate_response(SelfUserModel, 200) @validate_response(SelfUserModel, 200)
async def edit_user(data: EditUserRequest): async def edit_user(data: EditUserRequest):
"""Updates the current user."""
async with async_session() as session: async with async_session() as session:
user = await session.scalar(select(User).where(User.id == g.user.id)) user = await session.scalar(select(User).where(User.id == g.user.id))
@ -61,3 +64,32 @@ async def edit_user(data: EditUserRequest):
await session.commit() await session.commit()
return SelfUserModel.model_validate(user) return SelfUserModel.model_validate(user)
class DebugUserData(BasePatchModel):
username: str
class DebugUserResponse(SelfUserModel):
token: str
@bp.post("/api/v2/users/debug", host=BASE_DOMAIN)
@validate_request(DebugUserData)
@validate_response(DebugUserResponse, 200)
async def debug_create_user(data: DebugUserData):
"""Creates a user from just a username, and returns it along with a token.
FIXME: this must be removed **BEFORE** deploying to production (or even public testing)
"""
async with async_session() as session:
user = User(id=Snowflake.generate_int(), username=data.username)
await session.commit()
session.add(user)
token = await create_token(session, user, ["*"])
await session.commit()
await user.awaitable_attrs.members
user.token = generate_token(token)
return DebugUserResponse.model_validate(user)

View file

@ -1,7 +1,30 @@
from pydantic import Field from pydantic import Field, field_validator
from . import BasePatchModel
from .fields import FieldEntry, ProfileField, PronounEntry
from .user import BaseMemberModel, BaseUserModel from .user import BaseMemberModel, BaseUserModel
class FullMemberModel(BaseMemberModel): class FullMemberModel(BaseMemberModel):
user: BaseUserModel user: BaseUserModel
class MemberPatchModel(BasePatchModel):
name: str | None = Field(
min_length=1,
max_length=100,
default=None,
pattern=r"^[^@\?!#\/\\\[\]\"\{\}'$%&()+<=>^|~`,\*]{1,100}$",
)
bio: str | None = Field(max_length=1024, default=None)
names: list[FieldEntry] = Field(default=[])
pronouns: list[PronounEntry] = Field(default=[])
fields: list[ProfileField] = Field(default=[])
@field_validator("name")
@classmethod
def check_name(cls, value):
if value in [".", "..", "edit"]:
raise ValueError("Name is not allowed")
return value