-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #15 from JohnGrubba/dev
Session Management
- Loading branch information
Showing
16 changed files
with
368 additions
and
29 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,9 @@ | ||
import pytest | ||
import datetime | ||
import uuid | ||
import bcrypt | ||
from tools import users_collection | ||
from tools import users_collection, sessions_collection | ||
from bson import ObjectId | ||
|
||
|
||
@pytest.fixture | ||
|
@@ -15,7 +17,60 @@ def fixtureuser() -> dict: | |
"email": "[email protected]", | ||
"username": "FixtureUser", | ||
"createdAt": datetime.datetime.now(), | ||
"test": True, | ||
} | ||
users_collection.insert_one(user_data) | ||
result = users_collection.insert_one(user_data) | ||
user_data["password"] = "Kennwort1!" | ||
user_data["_id"] = str(result.inserted_id) | ||
return user_data | ||
|
||
|
||
@pytest.fixture | ||
def fixtureuser2() -> dict: | ||
users_collection.find_one_and_delete({"email": "[email protected]"}) | ||
hashed_pswd = bcrypt.hashpw("Kennwort1!".encode("utf-8"), bcrypt.gensalt(5)).decode( | ||
"utf-8" | ||
) | ||
user_data = { | ||
"password": hashed_pswd, | ||
"email": "[email protected]", | ||
"username": "FixtureUser1", | ||
"createdAt": datetime.datetime.now(), | ||
} | ||
result = users_collection.insert_one(user_data) | ||
user_data["password"] = "Kennwort1!" | ||
user_data["_id"] = str(result.inserted_id) | ||
return user_data | ||
|
||
|
||
@pytest.fixture | ||
def fixturesessiontoken_user(fixtureuser) -> tuple[str, dict]: | ||
sessions_collection.delete_many({}) | ||
# Generate a new session token | ||
session_token = str(uuid.uuid4()) | ||
# Persist the session | ||
session_id = sessions_collection.insert_one( | ||
{ | ||
"session_token": session_token, | ||
"user_id": ObjectId(fixtureuser["_id"]), | ||
"createdAt": datetime.datetime.now(), | ||
"device_information": {}, | ||
} | ||
) | ||
return session_token, fixtureuser, session_id.inserted_id | ||
|
||
|
||
@pytest.fixture | ||
def fixturesessiontoken_user2(fixtureuser2) -> tuple[str, dict]: | ||
# Generate a new session token | ||
session_token = str(uuid.uuid4()) | ||
# Persist the session | ||
session_id = sessions_collection.insert_one( | ||
{ | ||
"session_token": session_token, | ||
"user_id": ObjectId(fixtureuser2["_id"]), | ||
"createdAt": datetime.datetime.now(), | ||
"device_information": {}, | ||
} | ||
) | ||
return session_token, fixtureuser2, session_id.inserted_id |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
from fastapi.testclient import TestClient | ||
from crud.user import get_dangerous_user | ||
|
||
from .main import app | ||
|
||
client = TestClient(app) | ||
|
||
|
||
# Unauthorized Route Test | ||
def test_unauthorized_profile(): | ||
response = client.get("/profile") | ||
assert response.status_code == 401 | ||
|
||
|
||
def test_get_profile_invalid_session(): | ||
client.cookies.set("session", "invalid") | ||
response = client.get("/profile") | ||
assert response.status_code == 401 | ||
|
||
|
||
# Successfull tests | ||
def test_get_profile(fixturesessiontoken_user): | ||
client.cookies.set("session", fixturesessiontoken_user[0]) | ||
response = client.get("/profile") | ||
resp_json = response.json() | ||
assert response.status_code == 200 | ||
assert resp_json.get("email") == fixturesessiontoken_user[1]["email"] | ||
assert resp_json.get("username") == fixturesessiontoken_user[1]["username"] | ||
assert resp_json.get("createdAt") is not None | ||
assert resp_json.get("password") is None | ||
assert resp_json.get("_id") is None | ||
|
||
|
||
def test_update_username_valid(fixturesessiontoken_user): | ||
client.cookies.set("session", fixturesessiontoken_user[0]) | ||
response = client.patch("/profile", json={"username": "newusername"}) | ||
resp_json = response.json() | ||
assert response.status_code == 200 | ||
assert resp_json.get("email") == fixturesessiontoken_user[1]["email"] | ||
assert resp_json.get("username") == "newusername" | ||
assert resp_json.get("createdAt") is not None | ||
|
||
|
||
def test_update_email(fixturesessiontoken_user): | ||
client.cookies.set("session", fixturesessiontoken_user[0]) | ||
# E-Mail should not be updateable through this endpoint | ||
response = client.patch("/profile", json={"email": "[email protected]"}) | ||
resp_json = response.json() | ||
assert response.status_code == 200 | ||
assert resp_json.get("email") == fixturesessiontoken_user[1]["email"] | ||
assert resp_json.get("username") == fixturesessiontoken_user[1]["username"] | ||
assert resp_json.get("createdAt") is not None | ||
|
||
|
||
def test_update_password(fixturesessiontoken_user): | ||
client.cookies.set("session", fixturesessiontoken_user[0]) | ||
# Password should not be updateable through this endpoint | ||
response = client.patch("/profile", json={"password": "Kennwort2!"}) | ||
assert response.status_code == 200 | ||
assert ( | ||
get_dangerous_user(fixturesessiontoken_user[1]["_id"])["password"] | ||
!= "Kennwort2!" | ||
) | ||
|
||
|
||
def test_update_createdAt(fixturesessiontoken_user): | ||
client.cookies.set("session", fixturesessiontoken_user[0]) | ||
# Password should not be updateable through this endpoint | ||
response = client.patch("/profile", json={"createdAt": "1921"}) | ||
assert response.status_code == 200 | ||
assert get_dangerous_user(fixturesessiontoken_user[1]["_id"])["createdAt"] != "1921" | ||
|
||
|
||
def test_update_additional_data_valid(fixturesessiontoken_user): | ||
client.cookies.set("session", fixturesessiontoken_user[0]) | ||
# Data that is not existent, but updateable should be possible | ||
response = client.patch("/profile", json={"test2": "1921"}) | ||
assert response.status_code == 200 | ||
assert get_dangerous_user(fixturesessiontoken_user[1]["_id"]).get("test2") == "1921" | ||
|
||
|
||
def test_update_nonexistent_data(fixturesessiontoken_user): | ||
client.cookies.set("session", fixturesessiontoken_user[0]) | ||
# Additional data should not be updateable through this endpoint | ||
response = client.patch("/profile", json={"sas": "1921"}) | ||
assert response.status_code == 200 | ||
assert get_dangerous_user(fixturesessiontoken_user[1]["_id"]).get("sas") is None | ||
|
||
|
||
def test_update_additional_existent_data(fixturesessiontoken_user): | ||
client.cookies.set("session", fixturesessiontoken_user[0]) | ||
# Data that is additional but already exists should also be updateable | ||
response = client.patch("/profile", json={"test": "Ya"}) | ||
assert response.status_code == 200 | ||
assert get_dangerous_user(fixturesessiontoken_user[1]["_id"]).get("test") == "Ya" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
from fastapi import APIRouter, Depends, Response, HTTPException | ||
from api.dependencies.authenticated import get_user_dep | ||
from tools import bson_to_json | ||
from crud.sessions import get_user_sessions, delete_session, get_session_by_id | ||
from api.model import SessionListResponseModel | ||
|
||
router = APIRouter( | ||
prefix="/sessions", | ||
tags=["Sessions"], | ||
dependencies=[Depends(get_user_dep)], | ||
) | ||
|
||
|
||
@router.get("", response_model=SessionListResponseModel) | ||
async def sessions_list(user: dict = Depends(get_user_dep)): | ||
""" | ||
# Get Sessions | ||
## Description | ||
This endpoint is used to get the sessions of the user. | ||
""" | ||
sesss = get_user_sessions(user["_id"]) | ||
sesss = [bson_to_json(sess) for sess in sesss] | ||
return {"sessions": sesss} | ||
|
||
|
||
@router.delete("/{session_id}") | ||
async def delete_other_session(session_id: str, user: dict = Depends(get_user_dep)): | ||
""" | ||
# Delete Session | ||
## Description | ||
This endpoint is used to delete a session. | ||
""" | ||
sess_to_delete = get_session_by_id(session_id) | ||
if not sess_to_delete: | ||
raise HTTPException(status_code=404, detail="Session not found.") | ||
if sess_to_delete["user_id"] != user["_id"]: | ||
raise HTTPException(status_code=404, detail="Session not found.") | ||
delete_session(sess_to_delete["session_token"]) | ||
return Response(status_code=204) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
from fastapi.testclient import TestClient | ||
|
||
from .main import app | ||
|
||
|
||
client = TestClient(app) | ||
|
||
|
||
# SUCCESSFUL TESTS | ||
def test_get_sessions(fixturesessiontoken_user): | ||
client.cookies.set("session", fixturesessiontoken_user[0]) | ||
response = client.get("/sessions") | ||
resp_js = response.json() | ||
assert response.status_code == 200 | ||
assert isinstance(resp_js.get("sessions"), list) | ||
assert len(resp_js.get("sessions")) == 1 | ||
# Don't leak out session_token | ||
assert resp_js.get("sessions")[0].get("session_token") is None | ||
|
||
|
||
def test_delete_session(fixturesessiontoken_user): | ||
client.cookies.set("session", fixturesessiontoken_user[0]) | ||
response = client.delete("/sessions/" + str(fixturesessiontoken_user[2])) | ||
assert response.status_code == 204 | ||
|
||
|
||
def test_delete_session_otheracc(fixturesessiontoken_user, fixturesessiontoken_user2): | ||
client.cookies.set("session", fixturesessiontoken_user[0]) | ||
response = client.delete("/sessions/" + str(fixturesessiontoken_user2[2])) | ||
assert response.status_code == 404 | ||
|
||
|
||
def test_delete_session_nonexistent(fixturesessiontoken_user): | ||
client.cookies.set("session", fixturesessiontoken_user[0]) | ||
response = client.delete("/sessions/test") | ||
assert response.status_code == 404 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,5 @@ | ||
from fastapi.testclient import TestClient | ||
from tools import users_collection | ||
|
||
from .main import app | ||
|
||
|
@@ -37,6 +38,12 @@ def test_create_account_additional_data(): | |
assert response.status_code == 200 | ||
assert resp_js.get("session_token") is not None | ||
assert int(resp_js.get("expires")) is not None | ||
# Check which aditional data was saved | ||
usr = users_collection.find_one({"email": "[email protected]"}) | ||
# Check which data should be saved (testing_conf.json) | ||
assert usr.get("test") is True | ||
assert usr.get("test2") is None | ||
assert usr.get("test3") is None | ||
|
||
|
||
# MISSING DATA TESTS | ||
|
Oops, something went wrong.