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

View File

@ -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

View File

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

View File

@ -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()

View File

@ -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 = []

View File

@ -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)),

View File

@ -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":

View File

@ -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")