DaftAcademy / daftacademy-python_levelup-spring2020

20 stars 10 forks source link

Wykład 3, zadanie 2 - niepoprawny status code #30

Open jakubgierasimczyk opened 4 years ago

jakubgierasimczyk commented 4 years ago

Chciałbym spytać dlaczego poniższy kod nie przechodzi pierwszego testu z Zadania 2. Zdaje się, że wcześniej pojawiło się podobne pytanie, ale nie potrafiłem z niego wysnuć rozwzwiązania dla siebie.

Kiedy sprawdzam w /docs, to w terminalu widzę, że jest przekierowanie na /welcome. Status code ustawiam na 302, ale ostatecznie jest zwracany 200 (zdaje się, że z /welcome) i chyba dlatego nie przechodzi testu, ale nie wiem co z tym zrobić. Podobne problem pojawia się w Zadaniu 3

from starlette.responses import RedirectResponse
from fastapi.security import HTTPBasic, HTTPBasicCredentials
from fastapi import FastAPI, Response, status
from fastapi import Depends, Cookie, HTTPException
from hashlib import sha256

import secrets

app = FastAPI()

@app.get("/welcome")
def get_welcome():
    return "Hello!"

app.secret_key = "very constatn and random secret, best 64 characters"
app.tokens_list = []
security = HTTPBasic()

def get_current_username(credentials: HTTPBasicCredentials = Depends(security)):
    correct_username = secrets.compare_digest(credentials.username, "trudnY")
    correct_password = secrets.compare_digest(credentials.password, "PaC13Nt")
    print(f"{credentials.username}")
    print(f"{credentials.password}")
    if not (correct_username and correct_password):
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            # detail="Incorrect email or password",
            # headers={"WWW-Authenticate": "Basic"},
        )
    return credentials.username

@app.post("/login")
def login(
    user: str, password: str, response: Response,
    credentials_user = Depends(get_current_username)
    ):

    session_token = sha256(bytes(f"{user}{password}{app.secret_key}", encoding='utf8')).hexdigest()
    app.tokens_list.append(session_token)

    response.set_cookie(key="session_token", value=session_token)

    response = RedirectResponse(url = "/welcome")
    response.status_code = status.HTTP_302_FOUND

    return response
Obsttube commented 4 years ago

Edit: przypadkiem patrzyłem na kod innej osoby, ta odpowiedź nie jest relevant dla tego wątku

Przeczytaj "Principle" https://developer.mozilla.org/en-US/docs/Web/HTTP/Redirections

(W takich sytuacjach wpisujesz np. "http how to redirect" w Google. Powyżej podałem pierwszy link z Googla, rozwiązuje on twój problem.)

A i pamiętaj o zmianie app.secret :)

jakubgierasimczyk commented 4 years ago

Hm, niestety niewiele mi to pomogło. Może za długo już nad tym siedzę i/lub czegoś dogłębnie nie rozumiem. Info w powyższym linku potwierdza, że status code będzie 200 (z /welcome), a nie 3XX z przekierowania. To się zgadza z moimi obserwacjami, ale nie rozwiązuje problemu :)

Obsttube commented 4 years ago

Sorry, przypadkiem patrzyłem na kod kogoś komu na privie pomagałem! Zaraz zobaczę w czym może być u Ciebie problem.

Obsttube commented 4 years ago

Możesz podać dokładną treść błędu na repl.it?

jakubgierasimczyk commented 4 years ago

Pewnie:

Traceback (most recent call last):
  File "/home/runner/unit_tests.py", line 22, in test_method_login_success
    self.assertTrue(r1.status_code in (301, 302, 303, 307))
AssertionError: False is not true
jakubgierasimczyk commented 4 years ago
method_login_success
You have to redirect to APP_URL/hello page
Obsttube commented 4 years ago

Możesz jeszcze pokazać logi na heroku? https://dashboard.heroku.com/apps/XXXXX/logs

jakubgierasimczyk commented 4 years ago

O to chodzi?

2020-04-26T20:01:05.134593+00:00 heroku[web.1]: State changed from starting to up

2020-04-26T20:01:13.000000+00:00 app[api]: Build succeeded

2020-04-26T20:01:31.047331+00:00 heroku[router]: at=info method=POST path="/login" host=jg-python-level-up-1.herokuapp.com request_id=d6c24bb2-7eff-4093-bfdf-bf102db84f2a fwd="35.223.163.237" dyno=web.1 connect=1ms service=4ms status=422 bytes=314 protocol=https

2020-04-26T20:01:31.047359+00:00 app[web.1]: INFO:     35.223.163.237:0 - "POST /login HTTP/1.1" 422 Unprocessable Entity

2020-04-26T20:01:31.519978+00:00 heroku[router]: at=info method=POST path="/login" host=jg-python-level-up-1.herokuapp.com request_id=b7d33ddf-8d60-498f-8a16-5c02275f46c3 fwd="35.223.163.237" dyno=web.1 connect=1ms service=7ms status=401 bytes=160 protocol=https

2020-04-26T20:01:31.528053+00:00 app[web.1]: INFO:     35.223.163.237:0 - "POST /login HTTP/1.1" 401 Unauthorized

2020-04-26T20:07:09.166606+00:00 heroku[router]: at=info method=POST path="/login" host=jg-python-level-up-1.herokuapp.com request_id=7bc534c5-9891-46c9-bfa8-37f0b2b34da2 fwd="35.192.153.132" dyno=web.1 connect=1ms service=3ms status=422 bytes=314 protocol=https

2020-04-26T20:07:09.166687+00:00 app[web.1]: INFO:     35.192.153.132:0 - "POST /login HTTP/1.1" 422 Unprocessable Entity

2020-04-26T20:07:09.735498+00:00 heroku[router]: at=info method=POST path="/login" host=jg-python-level-up-1.herokuapp.com request_id=c241526c-dae7-4489-b882-16a46a868bf1 fwd="35.192.153.132" dyno=web.1 connect=0ms service=3ms status=401 bytes=160 protocol=https

2020-04-26T20:07:09.734727+00:00 app[web.1]: INFO:     35.192.153.132:0 - "POST /login HTTP/1.1" 401 Unauthorized
Obsttube commented 4 years ago

Patrząc tylko na kod, zdaje się, że w zły sposób przyjmujesz login i hasło. W login() przyjmujesz user: str, password: str, a nie powinieneś. To w funkcji get_current_username pobiera się login i hasło poprzez credentials.username i .password. Zatem ogólnie mówiąc, powinieneś usunąć user i password z login() oraz session_token generować w get_current_username, a następnie zwracać.

Edit: No i widzisz, w logach masz "422 Unprocessable Entity"

jakubgierasimczyk commented 4 years ago

Dobra nasza, zadanie 2 poszło, dzięki!