Profilsuche nach Nickname #41

Merged
weeman merged 1 commits from feature-nickname-search into main 2021-07-26 19:40:34 +02:00
7 changed files with 66 additions and 31 deletions

@ -113,6 +113,15 @@ curl -s \
http://localhost:5000/users/1/profile http://localhost:5000/users/1/profile
``` ```
Profilsuche nach Nickname:
```
curl -s \
-D "/dev/stderr" \
-H "Authorization: Bearer 22e6c5fc-8a5a-440e-b1f4-018deb9fd24e" \
http://localhost:5000/users/profiles
```
## Docker ## Docker

@ -7,3 +7,5 @@ peter:
password: geheim password: geheim
klaus: klaus:
password: jutta password: jutta
dieter:
password: hunger

@ -31,7 +31,7 @@ def seed(dev: bool):
skill_seed_file_path = app.config["KI_DATA_DIR"] + "/seed_data/skills.csv" skill_seed_file_path = app.config["KI_DATA_DIR"] + "/seed_data/skills.csv"
logging.info("importing skills") app.logger.info("importing skills")
with open(skill_seed_file_path) as skills_file: with open(skill_seed_file_path) as skills_file:
skills_csv_reader = csv.DictReader(skills_file) skills_csv_reader = csv.DictReader(skills_file)
@ -43,7 +43,7 @@ def seed(dev: bool):
if db_skill is None: if db_skill is None:
db.session.add(Skill(id=int(skill["id"]), name=skill["name"])) db.session.add(Skill(id=int(skill["id"]), name=skill["name"]))
logging.info("importing languages") app.logger.info("importing languages")
iso_seed_file_path = app.config["KI_DATA_DIR"] + "/seed_data/iso_639_1.csv" iso_seed_file_path = app.config["KI_DATA_DIR"] + "/seed_data/iso_639_1.csv"
@ -58,7 +58,7 @@ def seed(dev: bool):
db.session.add(Language(id=iso["639-1"], name=iso["Sprache"])) db.session.add(Language(id=iso["639-1"], name=iso["Sprache"]))
if dev: if dev:
logging.info("seeding peter :)") app.logger.info("seeding peter :)")
peter = User(auth_id="peter") peter = User(auth_id="peter")
db.session.add(peter) db.session.add(peter)
@ -105,9 +105,23 @@ def seed(dev: bool):
peter_fr = ProfileLanguage(profile=peters_profile, language_id="fr", level=3) peter_fr = ProfileLanguage(profile=peters_profile, language_id="fr", level=3)
db.session.add(peter_fr) db.session.add(peter_fr)
logging.info("seeding klaus :D") app.logger.info("seeding klaus :D")
klaus = User(auth_id="klaus") klaus = User(auth_id="klaus")
db.session.add(klaus) db.session.add(klaus)
app.logger.info("seeding dieter \\o/")
dieter = User(auth_id="dieter")
db.session.add(dieter)
dieters_profile = Profile(nickname="dirtydieter",
pronouns="",
volunteerwork="Müll sammeln",
availability="Nur nachts",
freetext="1001010010111!!!",
visible=True,
user=dieter)
db.session.add(dieters_profile)
db.session.commit() db.session.commit()

@ -18,11 +18,15 @@ def find_profiles():
if page_size > 100: if page_size > 100:
return make_response({"messages": {"page_size": "Die maximale Anzahl Einträge pro Seite beträgt 100"}}, 400) return make_response({"messages": {"page_size": "Die maximale Anzahl Einträge pro Seite beträgt 100"}}, 400)
offset = (page - 1) * page_size query = Profile.query.filter(Profile.visible.is_(True))
if "nickname" in request.args:
nickname = request.args.get("nickname")
query = query.filter(Profile.nickname.like(f"%{nickname}%"))
weeman marked this conversation as resolved Outdated
Outdated
Review

Possible SQL injection? Needs to be double checked

Possible SQL injection? Needs to be double checked

Laut Doku escaped SQLAlchemy das automagisch.
Aber lass einen Test reinpacken.

Laut Doku escaped SQLAlchemy das automagisch. Aber lass einen Test reinpacken.

Test eingefügt

Test eingefügt
query = Profile.query.filter(Profile.visible is True)
count = query.count() count = query.count()
offset = (page - 1) * page_size
db_profiles = query.limit(page_size).offset(offset).all() db_profiles = query.limit(page_size).offset(offset).all()
api_profiles = [] api_profiles = []

@ -53,7 +53,7 @@ class Profile(db.Model):
"availability": self.availability, "availability": self.availability,
"freetext": self.freetext, "freetext": self.freetext,
"visible": self.visible, "visible": self.visible,
"address": self.address.to_dict(), "address": self.address.to_dict() if self.address else None,
"contacts": list(map(lambda contact: contact.to_dict(), self.contacts)), "contacts": list(map(lambda contact: contact.to_dict(), self.contacts)),
"skills": list(map(lambda skill: skill.to_dict(), self.skills)), "skills": list(map(lambda skill: skill.to_dict(), self.skills)),
"searchtopics": list(map(lambda searchtopic: searchtopic.to_dict(), self.searchtopics)), "searchtopics": list(map(lambda searchtopic: searchtopic.to_dict(), self.searchtopics)),

@ -7,36 +7,35 @@ import unittest
from ki.test.ApiTest import ApiTest from ki.test.ApiTest import ApiTest
class TestSkillsEndpoint(ApiTest): class TestFindProfilesEndpoint(ApiTest):
def test_skills_options(self): def test_find_profiles_options(self):
response = self.client.options("/skills") response = self.client.options("/users/profiles")
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
self.assertIn("Access-Control-Allow-Origin", response.headers) self.assertIn("Access-Control-Allow-Origin", response.headers)
self.assertEqual(response.headers["Access-Control-Allow-Origin"], "*") self.assertEqual(response.headers["Access-Control-Allow-Origin"], "*")
def test_get_skills1(self): def test_find_nobody(self):
token = self.login("peter", "geheim")["token"] token = self.login("peter", "geheim")["token"]
response = self.client.get("/skills?search=p", headers={"Authorization": "Bearer " + token}) response = self.client.get("/users/profiles?nickname=horsthorsthorst",
headers={"Authorization": "Bearer " + token})
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
self.assertEqual( self.assertEqual(response.json, {"total": 0, "profiles": []})
{
"skills": [{ def test_find_sql_specialchars(self):
"id": 1, token = self.login("peter", "geheim")["token"]
"name": "PHP",
"icon_url": "/skills/1/icon" response = self.client.get("/users/profiles?nickname=%22%27%25", headers={"Authorization": "Bearer " + token})
}, { self.assertEqual(response.status_code, 200)
"id": 10, self.assertEqual(response.json, {"total": 0, "profiles": []})
"name": "PostgreSQL",
"icon_url": "/skills/10/icon" def test_find_all(self):
}, { token = self.login("peter", "geheim")["token"]
"id": 3,
"name": "Python", response = self.client.get("/users/profiles", headers={"Authorization": "Bearer " + token})
"icon_url": "/skills/3/icon" self.assertEqual(response.status_code, 200)
}] self.assertDictContainsSubset({"total": 1}, response.json)
}, response.json) self.assertDictContainsSubset({"nickname": "dirtydieter"}, response.json["profiles"][0])
self.assertIn("Access-Control-Allow-Origin", response.headers)
self.assertEqual(response.headers["Access-Control-Allow-Origin"], "*")
if __name__ == "main": if __name__ == "main":

@ -174,7 +174,14 @@ class TestProfileEndpoint(ApiTest):
response = self.client.get("/users/1/profile") response = self.client.get("/users/1/profile")
self.assertEqual(response.status_code, 401) self.assertEqual(response.status_code, 401)
def test_get_profile(self): def test_get_visible_proifle(self):
token = self.login("peter", "geheim")["token"]
response = self.client.get("/users/3/profile", headers={"Authorization": f"Bearer {token}"})
self.assertEqual(response.status_code, 200)
def test_get_own_profile(self):
login_data = {"username": "peter", "password": "geheim"} login_data = {"username": "peter", "password": "geheim"}
login_response = self.client.post("/users/login", data=json.dumps(login_data), content_type="application/json") login_response = self.client.post("/users/login", data=json.dumps(login_data), content_type="application/json")