Compare commits
20 Commits
feature/#4
...
delete-a-u
Author | SHA1 | Date | |
---|---|---|---|
fc1681928b | |||
dea781cc29 | |||
4fab7d7cda | |||
a3919d5d51
|
|||
9baf08d6b6
|
|||
733499303f
|
|||
111d4f08f4
|
|||
1287893698
|
|||
9dc9761a1a
|
|||
f0d05bbf22
|
|||
b63c0f3ede | |||
794eb7456c | |||
2387fb5e19 | |||
bfeb53cad7 | |||
763b6d6ee5
|
|||
55b83f6efa | |||
803353fdd3 | |||
cac14b4cfb | |||
8772a13163 | |||
f131ee335c |
@ -26,6 +26,9 @@ steps:
|
||||
from_secret: "docker_username"
|
||||
password:
|
||||
from_secret: "docker_password"
|
||||
when:
|
||||
branch:
|
||||
- main
|
||||
|
||||
image_pull_secrets:
|
||||
- dockerconfig
|
||||
|
@ -2,6 +2,7 @@
|
||||
#
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
repos:
|
||||
- repo: local
|
||||
hooks:
|
||||
- id: flake8
|
||||
|
28
README.md
28
README.md
@ -9,6 +9,32 @@ SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
[](https://drone.wtf-eg.de/kompetenzinventar/ki-backend)
|
||||
[](https://api.reuse.software/info/git.wtf-eg.de/kompetenzinventar/ki-backend)
|
||||
|
||||
## Über
|
||||
|
||||
Dieses Repo enthält das Backend des Projekts Kompentenzinventar - einer Webapplikation zur Erfassung von Userprofilen für die WTF eG.
|
||||
|
||||
Implementiert ist das Backend mit Flask.
|
||||
|
||||
### Mitmachen
|
||||
|
||||
Du kannst gerne bei der Entwicklung des Kompetenzinventars mitmachen.
|
||||
|
||||
- Fehler oder fehlende Funktionen erfassen. Bitte direkt über die [Issues](https://git.wtf-eg.de/kompetenzinventar/ki-backend/issues) in Gitea.
|
||||
- Dokumentation oder Implementierung verbessern. Bitte forke hierzu das Projekt, branche von `main` ab und erstelle dann einen [Pull Request](https://git.wtf-eg.de/kompetenzinventar/ki-backend/pulls).
|
||||
|
||||
### Kommunikation
|
||||
|
||||
Folgende Kanäle gibt es für die Kommunikation über das Kompetenzinventar:
|
||||
|
||||
- Die [Issues](https://git.wtf-eg.de/kompetenzinventar/ki-backend/issues) im WTF Gitea.
|
||||
- Den Bereich [AG Entwicklung](https://forum.wtf-eg.de/c/interna/ag-entwicklung/21) im WTF Forum.
|
||||
- Einen Raum in Matrix. Zutritt per Einladung, frlan lädt ein, eine einfache PN im Forum reicht.
|
||||
|
||||
### Repos
|
||||
|
||||
* **[ki-backend](https://git.wtf-eg.de/kompetenzinventar/ki-backend)** (dieses Repo) enthält das Backend
|
||||
* [ki-frontend](https://git.wtf-eg.de/kompetenzinventar/ki-frontend) enthält das Frontend
|
||||
* Weitere Repositories befinden sich in der Gitea Organisation [Kompetenzinventar](https://git.wtf-eg.de/kompetenzinventar).
|
||||
## Entwicklung
|
||||
|
||||
### Abhängigkeiten
|
||||
@ -22,7 +48,7 @@ SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
Ggf. vorher aufräumen
|
||||
|
||||
```
|
||||
rm data/ki.sqlite
|
||||
rm storage/ki.sqlite
|
||||
```
|
||||
|
||||
```
|
||||
|
2
app.py
2
app.py
@ -38,7 +38,7 @@ app.config["KI_LDAP_BASE_DN"] = os.getenv("KI_LDAP_BASE_DN")
|
||||
|
||||
CORS(app)
|
||||
db = SQLAlchemy(app)
|
||||
migrate = Migrate(app, db)
|
||||
migrate = Migrate(app, db, compare_type=True)
|
||||
|
||||
logging.debug("Hello from KI")
|
||||
|
||||
|
@ -3,3 +3,4 @@
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
from ki.actions.seed import seed # noqa
|
||||
from ki.actions.delete_profile import delete_profile # noqa
|
||||
|
52
ki/actions/delete_profile.py
Normal file
52
ki/actions/delete_profile.py
Normal file
@ -0,0 +1,52 @@
|
||||
# SPDX-FileCopyrightText: WTF Kooperative eG <https://wtf-eg.de/>
|
||||
#
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
from sqlalchemy.exc import NoResultFound
|
||||
from app import app, db
|
||||
from ki.models import User
|
||||
import sys
|
||||
|
||||
|
||||
def delete_profile(nickname: str):
|
||||
|
||||
# Getting the user
|
||||
try:
|
||||
user = User.query.filter(User.auth_id.__eq__(nickname)).one()
|
||||
except NoResultFound:
|
||||
sys.exit(f'Username »{nickname}« not found')
|
||||
|
||||
app.logger.info(f'Starting to delete user »{nickname}.')
|
||||
|
||||
# Deleting associated languages skills
|
||||
try:
|
||||
for language in (user.profile.languages):
|
||||
print(language.language_id)
|
||||
app.logger.info(f'Deleting language skil »{language.language_id}« for »{nickname}«.')
|
||||
db.session.delete(language)
|
||||
db.session.commit()
|
||||
except AttributeError:
|
||||
# No languages left over
|
||||
pass
|
||||
|
||||
# Deleting associated skills
|
||||
try:
|
||||
app.logger.info(f'Deleting skils for »{nickname}«.')
|
||||
for skill in user.profile.skills:
|
||||
db.session.delete(skill)
|
||||
db.session.commit()
|
||||
except AttributeError:
|
||||
# No skills left over
|
||||
pass
|
||||
|
||||
# Cleaning up profile
|
||||
try:
|
||||
app.logger.info(f'Deleting profile for »{nickname}«.')
|
||||
db.session.delete(user.profile)
|
||||
except:
|
||||
# No profile to be deleted
|
||||
pass
|
||||
# Deleting the user
|
||||
app.logger.info(f'Delete user »{nickname}«.')
|
||||
db.session.delete(user)
|
||||
db.session.commit()
|
@ -26,7 +26,15 @@ def seed_contacttypes():
|
||||
db.session.add(ContactType(id=int(contacttype["id"]), name=contacttype["name"]))
|
||||
|
||||
|
||||
def seed_user(nickname, visible=False, skills=[], languages=[], volunteerwork="", availability="", freetext=""):
|
||||
def seed_user(nickname,
|
||||
visible=False,
|
||||
skills=[],
|
||||
languages=[],
|
||||
volunteerwork="",
|
||||
availability_status=False,
|
||||
freetext="",
|
||||
availability_text="",
|
||||
availability_hours_per_week=42):
|
||||
app.logger.info(f"seeding {nickname} \\o/")
|
||||
|
||||
user = User(auth_id=nickname)
|
||||
@ -35,7 +43,9 @@ def seed_user(nickname, visible=False, skills=[], languages=[], volunteerwork=""
|
||||
profile = Profile(nickname=nickname,
|
||||
pronouns="",
|
||||
volunteerwork=volunteerwork,
|
||||
availability=availability,
|
||||
availability_status=availability_status,
|
||||
availability_text=availability_text,
|
||||
availability_hours_per_week=availability_hours_per_week,
|
||||
freetext=freetext,
|
||||
visible=visible,
|
||||
user=user)
|
||||
@ -91,7 +101,9 @@ def seed(dev: bool):
|
||||
peters_profile = Profile(nickname="peternichtlustig",
|
||||
pronouns="Herr Dr. Dr.",
|
||||
volunteerwork="Gartenverein",
|
||||
availability="Immer",
|
||||
availability_status=True,
|
||||
availability_hours_per_week=42,
|
||||
availability_text="Immer",
|
||||
freetext="Ich mag Kaffee",
|
||||
user=peter)
|
||||
db.session.add(peters_profile)
|
||||
@ -135,7 +147,9 @@ def seed(dev: bool):
|
||||
seed_user("dirtydieter",
|
||||
visible=True,
|
||||
volunteerwork="Müll sammeln",
|
||||
availability="Nur nachts",
|
||||
availability_status=True,
|
||||
availability_hours_per_week=24,
|
||||
availability_text="Nur Nachts!",
|
||||
freetext="1001010010111!!!",
|
||||
skills=[(Skill.skill_id_php, 5)])
|
||||
|
||||
|
@ -6,9 +6,19 @@ import click
|
||||
|
||||
from app import app
|
||||
from ki.actions import seed
|
||||
from ki.actions import delete_profile
|
||||
|
||||
|
||||
@app.cli.command("seed")
|
||||
@click.option("--dev", is_flag=True)
|
||||
def seed_command(dev):
|
||||
seed(dev)
|
||||
|
||||
|
||||
@app.cli.command("delete", help="Delete a user profile")
|
||||
@click.option(
|
||||
"--profile",
|
||||
help="Username of profile",
|
||||
)
|
||||
def delete_command(profile):
|
||||
delete_profile(profile)
|
||||
|
@ -30,19 +30,19 @@ def update_languages(profile, languages_data):
|
||||
profile_language_ids = []
|
||||
|
||||
for language_data in languages_data:
|
||||
language_id = language_data["language"]["id"]
|
||||
language = Language.query.get(language_id)
|
||||
if "id" not in language_data["language"]:
|
||||
continue
|
||||
|
||||
language = Language.query.get(language_data["language"]["id"])
|
||||
profile_language = ProfileLanguage.query.filter(ProfileLanguage.profile == profile,
|
||||
ProfileLanguage.language_id == language_id).first()
|
||||
ProfileLanguage.language == language).first()
|
||||
|
||||
if profile_language is None:
|
||||
profile_language = ProfileLanguage(profile=profile, language=language)
|
||||
db.session.add(profile_language)
|
||||
|
||||
profile_language.level = language_data["level"]
|
||||
|
||||
profile_language_ids.append(language_id)
|
||||
profile_language_ids.append(language.id)
|
||||
|
||||
ProfileLanguage.query.filter(ProfileLanguage.profile == profile,
|
||||
not_(ProfileLanguage.language_id.in_(profile_language_ids))).delete()
|
||||
@ -133,9 +133,21 @@ def update_profile(user_id: int):
|
||||
profile = Profile(user=user, nickname=user.auth_id)
|
||||
db.session.add(profile)
|
||||
|
||||
profile.nickname = request.json.get("nickname", "")
|
||||
profile.pronouns = request.json.get("pronouns", "")
|
||||
profile.volunteerwork = request.json.get("volunteerwork", "")
|
||||
profile.availability = request.json.get("availability", "")
|
||||
profile.availability_status = request.json.get("availability_status", False)
|
||||
profile.availability_text = request.json.get("availability_text", "")
|
||||
|
||||
availability_hours_per_week_raw = request.json.get("availability_hours_per_week", 0)
|
||||
|
||||
try:
|
||||
availability_hours_per_week = int(availability_hours_per_week_raw)
|
||||
except:
|
||||
availability_hours_per_week = None
|
||||
|
||||
profile.availability_hours_per_week = availability_hours_per_week
|
||||
|
||||
profile.freetext = request.json.get("freetext", "")
|
||||
profile.visible = request.json.get("visible", False)
|
||||
|
||||
|
12
ki/models.py
12
ki/models.py
@ -32,7 +32,11 @@ class Profile(db.Model):
|
||||
pronouns = Column(String(25), default="")
|
||||
volunteerwork = Column(String(4000), default="")
|
||||
freetext = Column(String(4000), default="")
|
||||
availability = Column(String(4000), default="")
|
||||
|
||||
availability_status = Column(Boolean, default=False)
|
||||
availability_text = Column(String(4000), default="")
|
||||
availability_hours_per_week = Column(Integer, default=0)
|
||||
|
||||
visible = Column(Boolean, nullable=False, default=False)
|
||||
created = Column(DateTime, nullable=False, default=datetime.now)
|
||||
updated = Column(DateTime, onupdate=datetime.now, nullable=False, default=datetime.now)
|
||||
@ -50,7 +54,9 @@ class Profile(db.Model):
|
||||
"nickname": self.nickname,
|
||||
"pronouns": self.pronouns,
|
||||
"volunteerwork": self.volunteerwork,
|
||||
"availability": self.availability,
|
||||
"availability_status": self.availability_status,
|
||||
"availability_text": self.availability_text,
|
||||
"availability_hours_per_week": self.availability_hours_per_week,
|
||||
"freetext": self.freetext,
|
||||
"visible": self.visible,
|
||||
"address": self.address.to_dict() if self.address else None,
|
||||
@ -143,7 +149,7 @@ class Skill(db.Model):
|
||||
__tablename__ = "skill"
|
||||
|
||||
id = Column(Integer, primary_key=True)
|
||||
name = Column(String(25), unique=True, nullable=False)
|
||||
name = Column(String(50), unique=True, nullable=False)
|
||||
|
||||
profiles = relationship("ProfileSkill", back_populates="skill")
|
||||
searchtopics = relationship("ProfileSearchtopic", back_populates="skill")
|
||||
|
@ -31,9 +31,12 @@ class TestProfileEndpoint(ApiTest):
|
||||
token = self.login("peter", "geheim")["token"]
|
||||
|
||||
data = {
|
||||
"nickname": "Hebbert",
|
||||
"pronouns": "Monsieur",
|
||||
"volunteerwork": "ja",
|
||||
"availability": "Nie",
|
||||
"availability_status": False,
|
||||
"availability_text": "Nie",
|
||||
"availability_hours_per_week": "23",
|
||||
"freetext": "Hallo",
|
||||
"visible": True,
|
||||
"address": {
|
||||
@ -108,9 +111,12 @@ class TestProfileEndpoint(ApiTest):
|
||||
with app.app_context():
|
||||
user = User.query.filter(User.id == 1).first()
|
||||
profile = user.profile
|
||||
self.assertEqual("Hebbert", profile.nickname)
|
||||
self.assertEqual("Monsieur", profile.pronouns)
|
||||
self.assertEqual("ja", profile.volunteerwork)
|
||||
self.assertEqual("Nie", profile.availability)
|
||||
self.assertEqual(False, profile.availability_status)
|
||||
self.assertEqual("Nie", profile.availability_text)
|
||||
self.assertEqual(23, profile.availability_hours_per_week)
|
||||
self.assertEqual("Hallo", profile.freetext)
|
||||
self.assertTrue(profile.visible)
|
||||
|
||||
@ -198,7 +204,9 @@ class TestProfileEndpoint(ApiTest):
|
||||
"user_id": 1,
|
||||
"nickname": "peternichtlustig",
|
||||
"pronouns": "Herr Dr. Dr.",
|
||||
"availability": "Immer",
|
||||
"availability_status": True,
|
||||
"availability_hours_per_week": 42,
|
||||
"availability_text": "Immer",
|
||||
"freetext": "Ich mag Kaffee",
|
||||
"volunteerwork": "Gartenverein",
|
||||
"visible": False,
|
||||
|
41
migrations/versions/459520b01f34_.py
Normal file
41
migrations/versions/459520b01f34_.py
Normal file
@ -0,0 +1,41 @@
|
||||
"""empty message
|
||||
|
||||
Revision ID: 459520b01f34
|
||||
Revises: 9183e2335b05
|
||||
Create Date: 2021-10-03 14:45:30.389359
|
||||
|
||||
"""
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
from sqlalchemy.sql import expression
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = '459520b01f34'
|
||||
down_revision = '9183e2335b05'
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
with op.batch_alter_table("profile") as batch_op:
|
||||
batch_op.alter_column('availability',
|
||||
new_column_name='availability_text',
|
||||
existing_type=sa.String(4000),
|
||||
existing_server_default="")
|
||||
batch_op.add_column(
|
||||
sa.Column('availability_status', sa.Boolean(), server_default=expression.true(), nullable=False))
|
||||
batch_op.add_column(sa.Column('availability_hours_per_week', sa.Integer(), nullable=True))
|
||||
# ### end Alembic commands ###
|
||||
|
||||
|
||||
def downgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
with op.batch_alter_table("profile") as batch_op:
|
||||
batch_op.alter_column('availability_text',
|
||||
new_column_name='availability',
|
||||
existing_type=sa.String(4000),
|
||||
existing_serve_server_default="")
|
||||
batch_op.drop_column('availability_hours_per_week')
|
||||
batch_op.drop_column('availability_status')
|
||||
# ### end Alembic commands ###
|
@ -0,0 +1,24 @@
|
||||
"""extend skill length to 50 chars
|
||||
|
||||
Revision ID: b5023977cbda
|
||||
Revises: 459520b01f34
|
||||
Create Date: 2021-11-22 20:07:19.188217
|
||||
|
||||
"""
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = 'b5023977cbda'
|
||||
down_revision = '459520b01f34'
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade():
|
||||
with op.batch_alter_table("skill") as batch_op:
|
||||
batch_op.alter_column('name',
|
||||
existing_type=sa.VARCHAR(length=25),
|
||||
type_=sa.String(length=50),
|
||||
existing_nullable=False)
|
Reference in New Issue
Block a user