Compare commits

..

3 Commits

18 changed files with 604 additions and 890 deletions

View File

@ -4,107 +4,48 @@
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
kind: pipeline kind: pipeline
type: docker type: docker
name: qa name: default
trigger:
event:
- push
- pull_request
branch:
- main
steps: steps:
- name: install-lint-test - name: qa
image: git.wtf-eg.de/kompetenzinventar/builder:1.0.2 image: registry.wtf-eg.net/ki-backend-builder:1.0.0
commands: commands:
- pipenv install --dev - pipenv install --dev
- pipenv run flake8 - pipenv run flake8
- pipenv run reuse lint - pipenv run reuse lint
- pipenv run python -m unittest discover ki - pipenv run python -m unittest discover ki
- name: docker-publish
image: plugins/docker
settings:
registry: registry.wtf-eg.net
repo: registry.wtf-eg.net/ki-backend
target: ki-backend
auto_tag: true
username:
from_secret: "docker_username"
password:
from_secret: "docker_password"
when:
event:
- push
branch:
- main
- name: docker-publish-tag
image: plugins/docker
settings:
registry: registry.wtf-eg.net
repo: registry.wtf-eg.net/ki-backend
target: ki-backend
auto_tag: true
username:
from_secret: "docker_username"
password:
from_secret: "docker_password"
when:
event:
- tag
image_pull_secrets: image_pull_secrets:
- dockerconfig - dockerconfig
---
kind: pipeline
type: docker
name: build
trigger:
event:
- push
branch:
- main
depends_on:
- qa
steps:
- name: docker-publish
image: plugins/docker
settings:
registry: git.wtf-eg.de
repo: git.wtf-eg.de/kompetenzinventar/backend
target: ki-backend
auto_tag: true
username:
from_secret: "docker_username"
password:
from_secret: "docker_password"
---
kind: pipeline
type: docker
name: deploy
trigger:
event:
- push
branch:
- main
depends_on:
- build
steps:
- name: deploy-dev
image: appleboy/drone-ssh
settings:
host:
- dev01.wtf-eg.net
username: drone_deployment
key:
from_secret: "dev01_deployment_key"
command_timeout: 2m
script:
- echo "Executing forced command..."
---
kind: pipeline
type: docker
name: tag-release
trigger:
event:
- tag
steps:
- name: install-lint-test
image: git.wtf-eg.de/kompetenzinventar/builder:1.0.2
commands:
- pipenv install --dev
- pipenv run flake8
- pipenv run reuse lint
- pipenv run python -m unittest discover ki
- name: docker-publish
image: plugins/docker
settings:
registry: git.wtf-eg.de
repo: git.wtf-eg.de/kompetenzinventar/backend
target: ki-backend
auto_tag: true
username:
from_secret: "docker_username"
password:
from_secret: "docker_password"

View File

@ -2,7 +2,7 @@
# #
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
FROM git.wtf-eg.de/kompetenzinventar/builder:1.0.2 as builder FROM registry.wtf-eg.net/ki-backend-builder:1.0.0 as builder
COPY Pipfile* ./ COPY Pipfile* ./
@ -10,7 +10,7 @@ RUN PIP_USER=1 PIP_IGNORE_INSTALLED=1 pipenv install --system --deploy --ignore-
RUN pip3 uninstall --yes pipenv RUN pip3 uninstall --yes pipenv
FROM git.wtf-eg.de/kompetenzinventar/base:1.0.2 as ki-backend FROM registry.wtf-eg.net/ki-backend-base:1.0.0 as ki-backend
# Install six explicitly. Otherwise Python complains about it missing. # Install six explicitly. Otherwise Python complains about it missing.
RUN pip3 install six RUN pip3 install six
@ -22,9 +22,4 @@ WORKDIR /app
COPY . . COPY . .
LABEL org.opencontainers.image.source=https://git.wtf-eg.de/kompetenzinventar/ki-backend.git
LABEL org.opencontainers.image.url=https://git.wtf-eg.de/kompetenzinventar/ki-backend
LABEL org.opencontainers.image.documentation=https://git.wtf-eg.de/kompetenzinventar/ki-backend#docker
LABEL org.opencontainers.image.vendor="WTF Kooperative eG"
CMD ["python3", "run_prod.py"] CMD ["python3", "run_prod.py"]

25
Pipfile
View File

@ -8,26 +8,25 @@ verify_ssl = true
name = "pypi" name = "pypi"
[packages] [packages]
flask = "~=3.0.0" flask = "~=2.0.1"
python-dotenv = "~=0.17.1" python-dotenv = "~=0.17.1"
flask-migrate = "~=4.0.5" flask-migrate = "~=3.0.1"
flask-sqlalchemy = "~=3.1.1" flask-sqlalchemy = "~=2.5.1"
sqlalchemy = "~=2.0.25" sqlalchemy = "~=1.4.18"
waitress = "~=2.1.2" waitress = "~=2.0.0"
pyyaml = "~=6.0.1" pyyaml = "~=5.4.1"
flask-cors = "~=4.0.0" flask-cors = "~=3.0.10"
ldap3 = "~=2.9.1" ldap3 = "~=2.9"
pymysql = "~=1.1.0" pymysql = "~=1.0.2"
werkzeug = "~=3.0.1"
[dev-packages] [dev-packages]
flake8 = "~=3.9.2" flake8 = "~=3.9.2"
yapf = "~=0.40.2" yapf = "~=0.31.0"
pre-commit = "~=2.13.0" pre-commit = "~=2.13.0"
reuse = "~=0.13.0" reuse = "~=0.13.0"
[requires] [requires]
python_version = "3.11" python_version = "3.8"
[scripts] [scripts]
clean = "rm storage/ki.sqlite" clean = "rm data/ki.sqlite"

976
Pipfile.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -222,6 +222,25 @@ docker-compose up
Dann http://localhost:13337 aufrufen. Dann http://localhost:13337 aufrufen.
### Workaround, falls der Zugriff auf registry.wtf-eg.net nicht möglich ist
Voraussetzung:
[ki-backend-docker](https://git.wtf-eg.de/kompetenzinventar/ki-backend-docker) muss parallel zum `ki-backend` ausgecheckt sein.
```
cd ki-backend-docker
docker build . --target base -t ki-backend-base
docker build . --target builder -t ki-backend-builder
```
Ändern der 2 Einträge im `Dockerfile` des `ki-backend`:
- registry.wtf-eg.net/ki-backend-builder:1.0.0 -> ki-backend-builder
- registry.wtf-eg.net/ki-backend-base:1.0.0 -> ki-backend-base
Danach sollte `docker-compose up` funktionieren.
## Lizenzen ## Lizenzen
Dieses Projekt erfüllt die [REUSE](https://reuse.software/) Spezifikation. Dieses Projekt erfüllt die [REUSE](https://reuse.software/) Spezifikation.

2
app.py
View File

@ -38,7 +38,7 @@ app.config["KI_LDAP_AUTH_PASSWORD"] = os.getenv("KI_LDAP_AUTH_PASSWORD")
app.config["KI_LDAP_BASE_DN"] = os.getenv("KI_LDAP_BASE_DN") app.config["KI_LDAP_BASE_DN"] = os.getenv("KI_LDAP_BASE_DN")
CORS(app) CORS(app)
db = SQLAlchemy(app, session_options={"future": True}) db = SQLAlchemy(app)
migrate = Migrate(app, db, compare_type=True) migrate = Migrate(app, db, compare_type=True)
app.logger.info("Hello from KI") app.logger.info("Hello from KI")

View File

@ -1,5 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="810" height="540">
<rect width="810" height="540" fill="#FCDD09"/>
<path stroke="#DA121A" stroke-width="60" d="M0,90H810m0,120H0m0,120H810m0,120H0"/>
</svg>

Before

Width:  |  Height:  |  Size: 242 B

View File

@ -2,7 +2,7 @@
# #
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
SQLALCHEMY_DATABASE_URI=sqlite:///../storage/ki.sqlite SQLALCHEMY_DATABASE_URI=sqlite:///storage/ki.sqlite
CORS_ORIGINS=* CORS_ORIGINS=*

View File

@ -1,6 +0,0 @@
# SPDX-FileCopyrightText: WTF Kooperative eG <https://wtf-eg.de/>
#
# SPDX-License-Identifier: AGPL-3.0-or-later
*
!.gitignore

View File

@ -1,4 +1,5 @@
# SPDX-FileCopyrightText: WTF Kooperative eG <https://wtf-eg.de/> # SPDX-FileCopyrightText: WTF Kooperative eG <https://wtf-eg.de/>
#
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
import csv import csv
@ -18,36 +19,28 @@ def seed_contacttypes():
for contacttype in csv_reader: for contacttype in csv_reader:
id = int(contacttype["id"]) id = int(contacttype["id"])
db_contacttype = db.session.get(ContactType, id) db_contacttype = ContactType.query.get(id)
if db_contacttype is None: if db_contacttype is None:
db.session.add(ContactType(id=int(contacttype["id"]), name=contacttype["name"])) db.session.add(ContactType(id=int(contacttype["id"]), name=contacttype["name"]))
def seed_user(auth_id, def seed_user(nickname,
nickname=None, visible=False,
pronouns="", skills=[],
visible=True, languages=[],
volunteerwork="", volunteerwork="",
availability_status=False, availability_status=False,
freetext="", freetext="",
availability_text="", availability_text="",
availability_hours_per_week=42, availability_hours_per_week=42):
skills=[],
searchtopics=[],
languages=[],
address=None,
contacts=[]):
if not nickname:
nickname = auth_id
app.logger.info(f"seeding {nickname} \\o/") app.logger.info(f"seeding {nickname} \\o/")
user = User(auth_id=auth_id) user = User(auth_id=nickname)
db.session.add(user) db.session.add(user)
profile = Profile(nickname=nickname, profile = Profile(nickname=nickname,
pronouns=pronouns, pronouns="",
volunteerwork=volunteerwork, volunteerwork=volunteerwork,
availability_status=availability_status, availability_status=availability_status,
availability_text=availability_text, availability_text=availability_text,
@ -60,31 +53,14 @@ def seed_user(auth_id,
skill = ProfileSkill(profile=profile, skill_id=skill_data[0], level=skill_data[1]) skill = ProfileSkill(profile=profile, skill_id=skill_data[0], level=skill_data[1])
db.session.add(skill) db.session.add(skill)
for skill_id in searchtopics:
searchtopic = ProfileSearchtopic(profile=profile, skill_id=skill_id)
db.session.add(searchtopic)
for language_data in languages: for language_data in languages:
language = ProfileLanguage(profile=profile, language_id=language_data[0], level=language_data[1]) language = ProfileLanguage(profile=profile, language_id=language_data[0], level=language_data[1])
db.session.add(language) db.session.add(language)
if address:
_address = Address(name=address[0],
street=address[1],
house_number=address[2],
additional=address[3],
postcode=address[4],
city=address[5],
country=address[6],
profile=profile)
db.session.add(_address)
for contact_data in contacts:
contact = Contact(profile=profile, contacttype_id=contact_data[0], content=contact_data[1])
db.session.add(contact)
db.session.add(profile) db.session.add(profile)
return profile
def seed(dev: bool): def seed(dev: bool):
seed_contacttypes() seed_contacttypes()
@ -98,7 +74,7 @@ def seed(dev: bool):
for skill in skills_csv_reader: for skill in skills_csv_reader:
id = int(skill["id"]) id = int(skill["id"])
db_skill = db.session.get(Skill, id) db_skill = Skill.query.get(id)
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"]))
@ -112,47 +88,86 @@ def seed(dev: bool):
for iso in iso_csv_reader: for iso in iso_csv_reader:
id = iso["639-1"] id = iso["639-1"]
db_language = db.session.get(Language, id) db_language = Language.query.get(id)
if db_language is None: if db_language is None:
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:
seed_user("klaus", visible=False) app.logger.info("seeding peter :)")
peter = User(auth_id="peter")
db.session.add(peter)
peters_profile = Profile(nickname="peternichtlustig",
pronouns="Herr Dr. Dr.",
volunteerwork="Gartenverein",
availability_status=True,
availability_hours_per_week=42,
availability_text="Immer",
freetext="Ich mag Kaffee",
user=peter)
db.session.add(peters_profile)
matrix_contact = Contact(profile=peters_profile, contacttype_id=4, content="@peter:wtf-eg.de")
db.session.add(matrix_contact)
email_contact = Contact(profile=peters_profile, contacttype_id=1, content="peter@wtf-eg.de")
db.session.add(email_contact)
peters_address = Address(name="Peter Nichtlustig",
street="Waldweg",
house_number="23i",
additional="Hinterhaus",
postcode="13337",
city="Bielefeld",
country="Deutschland",
profile=peters_profile)
db.session.add(peters_address)
peters_python_skill = ProfileSkill(profile=peters_profile, skill_id=3, level=3)
db.session.add(peters_python_skill)
peters_php_skill = ProfileSkill(profile=peters_profile, skill_id=1, level=5)
db.session.add(peters_php_skill)
peters_python_searchtopic = ProfileSearchtopic(profile=peters_profile, skill_id=3)
db.session.add(peters_python_searchtopic)
peters_php_searchtopic = ProfileSearchtopic(profile=peters_profile, skill_id=1)
db.session.add(peters_php_searchtopic)
peter_de = ProfileLanguage(profile=peters_profile, language_id="de", level=5)
db.session.add(peter_de)
peter_fr = ProfileLanguage(profile=peters_profile, language_id="fr", level=3)
db.session.add(peter_fr)
seed_user("klaus")
for i in range(1, 20): for i in range(1, 20):
seed_user(f"babsi{i}") seed_user(f"babsi{i}", visible=True)
seed_user("peter", dieter = seed_user("dirtydieter",
nickname="peternichtlustig", visible=True,
visible=False, volunteerwork="Müll sammeln",
pronouns="Herr Dr. Dr.", availability_status=True,
volunteerwork="Gartenverein", availability_hours_per_week=24,
availability_status=True, availability_text="Nur Nachts!",
availability_hours_per_week=42, freetext="1001010010111!!!",
availability_text="Immer", skills=[(Skill.skill_id_php, 5)])
freetext="Ich mag Kaffee",
skills=[(3, 3), (1, 5)],
searchtopics=[3, 1],
languages=[("de", 5), ("fr", 3)],
address=("Peter Nichtlustig", "Waldweg", "23i", "Hinterhaus", "13337", "Bielefeld", "Deutschland"),
contacts=[(4, "@peter:wtf-eg.de"), (1, "peter@wtf-eg.de")])
seed_user("dirtydieter", dieters_address = Address(name="Friedrich Witzig", profile=dieter)
volunteerwork="Müll sammeln", db.session.add(dieters_address)
availability_status=True,
availability_hours_per_week=24,
availability_text="Nur Nachts!",
freetext="1001010010111!!!",
skills=[(1, 5)],
address=("Friedrich Witzig", "", "", "", "", "", ""))
# all_skills = [(skill.id, 3) for skill in Skill.query.all()] # query causes problems
# seed_user("jutta", languages=[("fr", 5)], skills=all_skills)
seed_user("giesela", skills=[(9, 3), (10, 5)]) all_skills = Skill.query.all()
seed_user("bertha", visible=False, skills=[(11, 3), (10, 5)]) all_profile_skills = []
seed_user("monique", languages=[("fr", 4)]) for skill in all_skills:
print("seeding done") all_profile_skills.append((skill.id, 3))
with app.app_context():
db.session.commit() # also problematic seed_user("jutta", visible=True, languages=[("fr", 5)], skills=all_profile_skills)
print("commit done") seed_user("giesela", visible=True, skills=[(Skill.skill_id_mysql, 3), (Skill.skill_id_postgresql, 5)])
seed_user("bertha", visible=False, skills=[(Skill.skill_id_sqlite, 3), (Skill.skill_id_postgresql, 5)])
seed_user("monique", visible=True, languages=[("fr", 4)])
db.session.commit()

View File

@ -33,7 +33,7 @@ def update_languages(profile, languages_data):
if "id" not in language_data["language"]: if "id" not in language_data["language"]:
continue continue
language = db.session.get(Language, language_data["language"]["id"]) language = Language.query.get(language_data["language"]["id"])
profile_language = ProfileLanguage.query.filter(ProfileLanguage.profile == profile, profile_language = ProfileLanguage.query.filter(ProfileLanguage.profile == profile,
ProfileLanguage.language == language).first() ProfileLanguage.language == language).first()
@ -110,7 +110,7 @@ def update_contacts(profile, contacts_data):
if "id" in contact_data: if "id" in contact_data:
contact_id = int(contact_data["id"]) contact_id = int(contact_data["id"])
contact_ids_to_be_deleted.remove(contact_id) contact_ids_to_be_deleted.remove(contact_id)
contact = db.session.get(Contact, contact_id) contact = Contact.query.get(contact_id)
else: else:
contact = Contact(profile=profile, contacttype=contacttype) contact = Contact(profile=profile, contacttype=contacttype)
db.session.add(contact) db.session.add(contact)
@ -122,7 +122,7 @@ def update_contacts(profile, contacts_data):
def update_profile(user_id: int): def update_profile(user_id: int):
user = db.session.get(User, user_id) user = User.query.get(user_id)
if user is None: if user is None:
return make_response({}, 404) return make_response({}, 404)
@ -151,11 +151,11 @@ def update_profile(user_id: int):
profile.freetext = request.json.get("freetext", "") profile.freetext = request.json.get("freetext", "")
profile.visible = request.json.get("visible", False) profile.visible = request.json.get("visible", False)
update_address(profile, request.json.get("address")) update_address(profile, request.json.get("address", {}))
update_contacts(profile, request.json.get("contacts", [])) update_contacts(profile, request.json.get("contacts", {}))
update_skills(profile, request.json.get("skills", [])) update_skills(profile, request.json.get("skills", {}))
update_searchtopics(profile, request.json.get("searchtopics", [])) update_searchtopics(profile, request.json.get("searchtopics"))
update_languages(profile, request.json.get("languages", [])) update_languages(profile, request.json.get("languages", {}))
db.session.commit() db.session.commit()

View File

@ -139,6 +139,13 @@ class Address(db.Model):
class Skill(db.Model): class Skill(db.Model):
skill_id_php = 1
skill_id_python = 3
skill_id_sqlalchemy = 7
skill_id_mysql = 9
skill_id_postgresql = 10
skill_id_sqlite = 11
__tablename__ = "skill" __tablename__ = "skill"
id = Column(Integer, primary_key=True) id = Column(Integer, primary_key=True)

View File

@ -10,14 +10,13 @@ from ki.auth import auth
from ki.handlers import find_profiles as find_profiles_handler from ki.handlers import find_profiles as find_profiles_handler
from ki.handlers import update_profile as update_profile_handler from ki.handlers import update_profile as update_profile_handler
from ki.models import ContactType, Language, Skill, Token, User from ki.models import ContactType, Language, Skill, Token, User
from app import app, db from app import app
content_type_svg = "image/svg+xml" content_type_svg = "image/svg+xml"
content_type_png = "image/png" content_type_png = "image/png"
def token_auth(func): def token_auth(func):
@wraps(func) @wraps(func)
def _token_auth(*args, **kwargs): def _token_auth(*args, **kwargs):
auth_header = request.headers.get("Authorization") auth_header = request.headers.get("Authorization")
@ -66,7 +65,7 @@ def handle_completion_request(model, key):
def handle_icon_request(model, id, path): def handle_icon_request(model, id, path):
object = db.session.get(model, id) object = model.query.get(id)
if object is None: if object is None:
return make_response({}, 404) return make_response({}, 404)

View File

@ -1,5 +1,6 @@
# SPDX-FileCopyrightText: WTF Kooperative eG <https://wtf-eg.de/> # SPDX-FileCopyrightText: WTF Kooperative eG <https://wtf-eg.de/>
# SPDX-License-Identifier: AGPL-3.0-or-later #
# SPDX-License-Identifier: AGPL-3.0-or-later
from alembic import command from alembic import command
import json import json
@ -8,14 +9,12 @@ import unittest
from app import app, db, migrate from app import app, db, migrate
from ki.actions import seed from ki.actions import seed
from ki.models import Skill from ki.models import Skill
from sqlalchemy import select
class ApiTest(unittest.TestCase): class ApiTest(unittest.TestCase):
maxDiff = None maxDiff = None
def setUp(self): def setUp(self):
print("Running setup")
app.debug = True app.debug = True
app.config["KI_AUTH"] = "file" app.config["KI_AUTH"] = "file"
app.config["TESTING"] = True app.config["TESTING"] = True
@ -23,38 +22,19 @@ class ApiTest(unittest.TestCase):
self.client = app.test_client() self.client = app.test_client()
config = migrate.get_config()
with app.app_context(): with app.app_context():
config = migrate.get_config()
command.upgrade(config, "head") command.upgrade(config, "head")
seed(True)
# statement = select(Skill).order_by(Skill.id.desc()) seed(True)
# print(statement) max_skill = Skill.query.order_by(Skill.id.desc()).first()
# skill_obj = db.session.scalars(statement).all()
# print(skill_obj)
# statement = select(Skill.id)
# print(statement)
# max_skill = db.session.Skill().order_by(Skill.id.desc()).first()
# max_skill = Skill.query.order_by(Skill.id.desc()).first() # TODO: problematic
with db.session.no_autoflush: # only works on first test run
max_skill = db.session.query(Skill).order_by(Skill.id.desc()).first() # TODO: also problematic,
# skills = db.session.execute(db.select(Skill)).scalars()
# print(max_skill)
# max_skill = db.session.execute(db.select(Skill)
# .order_by(Skill.id.desc())
# ).scalar_one()
print(max_skill)
print("max_skill done")
self.max_skill_id = max_skill.id self.max_skill_id = max_skill.id
def tearDown(self): def tearDown(self):
print("Running teardown") db.drop_all()
with app.app_context(): db.engine.dispose()
db.drop_all()
db.engine.dispose()
def login(self, username, password): def login(self, username, password):
# with app.app_context():
login_data = {"username": username, "password": password} login_data = {"username": username, "password": password}
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")

View File

@ -1,4 +1,5 @@
# SPDX-FileCopyrightText: WTF Kooperative eG <https://wtf-eg.de/> # SPDX-FileCopyrightText: WTF Kooperative eG <https://wtf-eg.de/>
#
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
import unittest import unittest
@ -8,38 +9,35 @@ from ki.test.ApiTest import ApiTest
class TestContactTypesEndpoint(ApiTest): class TestContactTypesEndpoint(ApiTest):
def test_skills_options(self): def test_skills_options(self):
print("test_skills_options")
# with app.app_context():
response = self.client.options("/contacttypes") response = self.client.options("/contacttypes")
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_contacttypes_unauthorised(self): def test_get_contacttypes_unauthorised(self):
# print("test_get_contacttypes_unauthorised") response = self.client.get("/contacttypes?search=m")
# response = self.client.get("/contacttypes?search=m") self.assertEqual(response.status_code, 401)
# self.assertEqual(response.status_code, 401)
# def test_get_contacttypes(self): def test_get_contacttypes(self):
# token = self.login("peter", "geheim")["token"] token = self.login("peter", "geheim")["token"]
# response = self.client.get("/contacttypes?search=m", headers={"Authorization": "Bearer " + token}) response = self.client.get("/contacttypes?search=m", headers={"Authorization": "Bearer " + token})
# self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
# self.assertEqual( self.assertEqual(
# { {
# "contacttypes": [{ "contacttypes": [{
# "id": 5, "id": 5,
# "name": "Mastodon" "name": "Mastodon"
# }, { }, {
# "id": 4, "id": 4,
# "name": "Matrix" "name": "Matrix"
# }, { }, {
# "id": 2, "id": 2,
# "name": "Mobiltelefon" "name": "Mobiltelefon"
# }] }]
# }, response.json) }, response.json)
# 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"], "*")
if __name__ == "main": if __name__ == "main":

View File

@ -20,8 +20,7 @@ class TestProfileEndpoint(ApiTest):
self.assertEqual(login_response.status_code, 200) self.assertEqual(login_response.status_code, 200)
self.assertIn("token", login_response.json) self.assertIn("token", login_response.json)
babsi = User.query.filter(User.auth_id == "babsi1").first() response = self.client.post("/users/1/profile",
response = self.client.post(f"/users/{babsi.id}/profile",
data=json.dumps({}), data=json.dumps({}),
content_type="application/json", content_type="application/json",
headers={"Authorization": "Bearer " + login_response.json["token"]}) headers={"Authorization": "Bearer " + login_response.json["token"]})
@ -103,15 +102,14 @@ class TestProfileEndpoint(ApiTest):
"level": 2 "level": 2
}] }]
} }
peter = User.query.filter(User.auth_id == "peter").first() response = self.client.post("/users/1/profile",
response = self.client.post(f"/users/{peter.id}/profile",
data=json.dumps(data), data=json.dumps(data),
content_type="application/json", content_type="application/json",
headers={"Authorization": "Bearer " + token}) headers={"Authorization": "Bearer " + token})
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
with app.app_context(): with app.app_context():
user = User.query.filter(User.id == peter.id).first() user = User.query.filter(User.id == 1).first()
profile = user.profile profile = user.profile
self.assertEqual("Hebbert", profile.nickname) self.assertEqual("Hebbert", profile.nickname)
self.assertEqual("Monsieur", profile.pronouns) self.assertEqual("Monsieur", profile.pronouns)
@ -185,8 +183,7 @@ class TestProfileEndpoint(ApiTest):
def test_get_visible_proifle(self): def test_get_visible_proifle(self):
token = self.login("peter", "geheim")["token"] token = self.login("peter", "geheim")["token"]
babsi = User.query.filter(User.auth_id == "babsi1").first() response = self.client.get("/users/3/profile", headers={"Authorization": f"Bearer {token}"})
response = self.client.get(f"/users/{babsi.id}/profile", headers={"Authorization": f"Bearer {token}"})
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
@ -197,15 +194,14 @@ class TestProfileEndpoint(ApiTest):
self.assertEqual(login_response.status_code, 200) self.assertEqual(login_response.status_code, 200)
self.assertIn("token", login_response.json) self.assertIn("token", login_response.json)
peter = User.query.filter(User.auth_id == "peter").first() response = self.client.get("/users/1/profile",
response = self.client.get(f"/users/{peter.id}/profile",
headers={"Authorization": "Bearer " + login_response.json["token"]}) headers={"Authorization": "Bearer " + login_response.json["token"]})
profile_id = peter.profile.id
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
self.assertDictEqual( self.assertDictEqual(
response.json, { response.json, {
"profile": { "profile": {
"user_id": peter.id, "user_id": 1,
"nickname": "peternichtlustig", "nickname": "peternichtlustig",
"pronouns": "Herr Dr. Dr.", "pronouns": "Herr Dr. Dr.",
"availability_status": True, "availability_status": True,
@ -222,12 +218,12 @@ class TestProfileEndpoint(ApiTest):
"id": 1, "id": 1,
"name": "Peter Nichtlustig", "name": "Peter Nichtlustig",
"postcode": "13337", "postcode": "13337",
"profile_id": profile_id, "profile_id": 1,
"street": "Waldweg" "street": "Waldweg"
}, },
"contacts": [{ "contacts": [{
"id": 1, "id": 1,
"profile_id": profile_id, "profile_id": 1,
"contacttype": { "contacttype": {
"id": 4, "id": 4,
"name": "Matrix" "name": "Matrix"
@ -235,7 +231,7 @@ class TestProfileEndpoint(ApiTest):
"content": "@peter:wtf-eg.de" "content": "@peter:wtf-eg.de"
}, { }, {
"id": 2, "id": 2,
"profile_id": profile_id, "profile_id": 1,
"contacttype": { "contacttype": {
"id": 1, "id": 1,
"name": "E-Mail" "name": "E-Mail"
@ -243,7 +239,7 @@ class TestProfileEndpoint(ApiTest):
"content": "peter@wtf-eg.de" "content": "peter@wtf-eg.de"
}], }],
"skills": [{ "skills": [{
"profile_id": profile_id, "profile_id": 1,
"skill": { "skill": {
"id": 1, "id": 1,
"name": "PHP", "name": "PHP",
@ -251,7 +247,7 @@ class TestProfileEndpoint(ApiTest):
}, },
"level": 5 "level": 5
}, { }, {
"profile_id": profile_id, "profile_id": 1,
"skill": { "skill": {
"id": 3, "id": 3,
"name": "Python", "name": "Python",
@ -260,14 +256,14 @@ class TestProfileEndpoint(ApiTest):
"level": 3 "level": 3
}], }],
"searchtopics": [{ "searchtopics": [{
"profile_id": profile_id, "profile_id": 1,
"skill": { "skill": {
"id": 1, "id": 1,
"name": "PHP", "name": "PHP",
"icon_url": "/skills/1/icon" "icon_url": "/skills/1/icon"
} }
}, { }, {
"profile_id": profile_id, "profile_id": 1,
"skill": { "skill": {
"id": 3, "id": 3,
"name": "Python", "name": "Python",
@ -275,7 +271,7 @@ class TestProfileEndpoint(ApiTest):
} }
}], }],
"languages": [{ "languages": [{
"profile_id": profile_id, "profile_id": 1,
"language": { "language": {
"id": "de", "id": "de",
"name": "Deutsch", "name": "Deutsch",
@ -283,7 +279,7 @@ class TestProfileEndpoint(ApiTest):
}, },
"level": 5 "level": 5
}, { }, {
"profile_id": profile_id, "profile_id": 1,
"language": { "language": {
"id": "fr", "id": "fr",
"name": "Französisch", "name": "Französisch",

View File

@ -19,7 +19,7 @@ logger = logging.getLogger('alembic.env')
# target_metadata = mymodel.Base.metadata # target_metadata = mymodel.Base.metadata
config.set_main_option( config.set_main_option(
'sqlalchemy.url', 'sqlalchemy.url',
str(current_app.extensions['migrate'].db.engine.url).replace( str(current_app.extensions['migrate'].db.get_engine().url).replace(
'%', '%%')) '%', '%%'))
target_metadata = current_app.extensions['migrate'].db.metadata target_metadata = current_app.extensions['migrate'].db.metadata
@ -68,7 +68,7 @@ def run_migrations_online():
directives[:] = [] directives[:] = []
logger.info('No changes in schema detected.') logger.info('No changes in schema detected.')
connectable = current_app.extensions['migrate'].db.engine connectable = current_app.extensions['migrate'].db.get_engine()
with connectable.connect() as connection: with connectable.connect() as connection:
context.configure( context.configure(

View File

@ -11,4 +11,4 @@ with app.app_context():
config = migrate.get_config() config = migrate.get_config()
command.upgrade(config, "head") command.upgrade(config, "head")
serve(app, host="0.0.0.0", port=5000, threads=20) serve(app, host="0.0.0.0", port=5000)