Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sugestão sobre a validação do create_user #144

Closed
K-dash opened this issue May 14, 2024 · 2 comments · Fixed by #146
Closed

Sugestão sobre a validação do create_user #144

K-dash opened this issue May 14, 2024 · 2 comments · Fixed by #146

Comments

@K-dash
Copy link

K-dash commented May 14, 2024

Olá. Obrigado por este excelente projeto!
Atualmente, estou seguindo este material didático e estou aprendendo muito com o conteúdo altamente prático!

Tenho uma sugestão relacionada ao título.
Verifiquei que a validação no endpoint POST para criar um novo usuário (função create_user) está da seguinte forma nas seções
5 e 6, respectivamente.

Seção 5 (Integrando Banco de Dados a API)

/fast_zero/app.py
Neste ponto, a validação é feita conforme abaixo, verificando "se já existe um usuário com o mesmo username".

@app.post('/users/', status_code=HTTPStatus.CREATED, response_model=UserPublic)
def create_user(user: UserSchema, session: Session = Depends(get_session)):
    db_user = session.scalar(
        select(User).where(User.username == user.username)  # <-
    )

    if db_user:
        raise HTTPException(
            status_code=HTTPStatus.BAD_REQUEST,
            detail='Username already registered',
        )
...

Seção 6 (Autenticação e Autorização com JWT)

/fast_zero/app.py
Conforme abaixo, a verificação "se já existe um usuário com o mesmo username" implementada na seção 5 foi removida e substituída por uma verificação "se já existe um usuário com o mesmo email".
(Notei essa alteração somente mais tarde, pois não havia uma explicação específica sobre essa mudança e ela não estava destacada.)

@router.post('/', status_code=HTTPStatus.CREATED, response_model=UserPublic)
def create_user(user: UserSchema, session: Session):
    db_user = session.scalar(select(User).where(User.email == user.email))  # <--
    if db_user:
        raise HTTPException(
            status_code=HTTPStatus.BAD_REQUEST,
            detail='Email already registered',
        )
...

No modelo User, tanto o campo username quanto o email possuem a especificação unique=True.
Portanto, a partir da seção 6, ao criar um usuário por meio do Swagger UI, se for enviada uma solicitação POST com um "username que já existe no banco de dados", ocorrerá um ServerError.
(já que a validação do username foi removida na seção 6).

sqlalchemy.exc.IntegrityError: (sqlite3.IntegrityError) UNIQUE constraint failed: users.username
[SQL: INSERT INTO users (username, password, email) VALUES (?, ?, ?) RETURNING id, created_at]
[parameters: ('string', '$2b$12$sbvOc6JGKxNxmqTol1vfCugZOc4eM05kYQo0j8IIvM8OD9oCMVdJq', 'user2@example.com')]
(Background on this error at: https://sqlalche.me/e/20/gkpj)

Em vez de um ServerError, acredito que seja necessário retornar uma mensagem de erro apropriada para o cliente. Portanto, o que você acha de adicionar validações tanto para o email quanto para o username na função create_user, conforme abaixo?

@router.post("/", status_code=HTTPStatus.CREATED, response_model=UserPublic)
def create_user(user: UserSchema, session: Session):
    db_user = session.scalar(
        select(User).where(
            or_(User.username == user.username, User.email == user.email)
        )
    )

    if db_user:
        if db_user.username == user.username:
            raise HTTPException(
                status_code=HTTPStatus.BAD_REQUEST,
                detail="Username already exists",
            )
        elif db_user.email == user.email:
            raise HTTPException(
                status_code=HTTPStatus.BAD_REQUEST,
                detail="Email already exists",
            )
...

Desculpe-me por mencionar um detalhe tão pequeno, mas ficaria feliz em ouvir sua opinião.

@dunossauro
Copy link
Owner

@K-dash obrigado pleo retorno. Isso está acontecendo, pois estou trabalhando em refazer a aula 04 aos poucos, então algumas coisas acabam passando.

Adorei a solução proposta. Vou acabar aderindo ela aqui texto assim que tiver um tempo. Muito obrigado

@dunossauro
Copy link
Owner

(Só fazendo algumas anotações)

Isso tem impacto em todos os códigos fonte das aulas 5 pra frente

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants