Merge pull request 'visible, contacttypes' (#30) from feature-visible into main

Reviewed-on: 
This commit is contained in:
weeman 2021-07-05 17:55:00 +02:00
commit 1d2d1a27b4
8 changed files with 99 additions and 16 deletions

@ -0,0 +1,10 @@
id,name
1,E-Mail
2,Mobiltelefon
3,Festnetz
4,Matrix
5,Mastodon
6,Telegram
7,Jabber/XMPP
8,Web
9,Twitter
1 id name
2 1 E-Mail
3 2 Mobiltelefon
4 3 Festnetz
5 4 Matrix
6 5 Mastodon
7 6 Telegram
8 7 Jabber/XMPP
9 8 Web
10 9 Twitter

@ -5,7 +5,25 @@ from app import app, db
from ki.models import Address, Contact, ContactType, Language, Skill, Profile, ProfileLanguage, ProfileSkill, User
def seed_contacttypes():
contacttypes_seed_file_path = app.config["KI_DATA_DIR"] + "/seed_data/contacttypes.csv"
logging.info("importing contacttypes")
with open(contacttypes_seed_file_path) as file:
csv_reader = csv.DictReader(file)
for contacttype in csv_reader:
id = int(contacttype["id"])
db_contacttype = ContactType.query.get(id)
if db_contacttype is None:
db.session.add(ContactType(id=int(contacttype["id"]), name=contacttype["name"]))
def seed(dev: bool):
seed_contacttypes()
skill_seed_file_path = app.config["KI_DATA_DIR"] + "/seed_data/skills.csv"
logging.info("importing skills")
@ -47,16 +65,10 @@ def seed(dev: bool):
user=peter)
db.session.add(peters_profile)
matrix_type = ContactType(name="Matrix")
db.session.add(matrix_type)
matrix_contact = Contact(profile=peters_profile, contacttype=matrix_type, content="@peter:wtf-eg.de")
matrix_contact = Contact(profile=peters_profile, contacttype_id=4, content="@peter:wtf-eg.de")
db.session.add(matrix_contact)
email_type = ContactType(name="E-Mail")
db.session.add(email_type)
email_contact = Contact(profile=peters_profile, contacttype=email_type, content="peter@wtf-eg.de")
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",

@ -107,6 +107,7 @@ def update_profile(user_id: int):
profile.pronouns = request.json.get("pronouns", "")
profile.volunteerwork = request.json.get("volunteerwork", "")
profile.freetext = request.json.get("freetext", "")
profile.visible = request.json.get("visible", False)
update_address(profile, request.json.get("address", {}))
update_contacts(profile, request.json.get("contacts", {}))

@ -1,6 +1,6 @@
from datetime import datetime
from sqlalchemy import Column, Integer, SmallInteger, String, DateTime, ForeignKey
from sqlalchemy import Boolean, Column, Integer, SmallInteger, String, DateTime, ForeignKey
from sqlalchemy.orm import relationship
from app import db
@ -28,6 +28,7 @@ class Profile(db.Model):
pronouns = Column(String(25), default="")
volunteerwork = Column(String(4000), default="")
freetext = Column(String(4000), default="")
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)
@ -44,6 +45,7 @@ class Profile(db.Model):
"pronouns": self.pronouns,
"volunteerwork": self.volunteerwork,
"freetext": self.freetext,
"visible": self.visible,
"address": self.address.to_dict(),
"contacts": list(map(lambda contact: contact.to_dict(), self.contacts)),
"skills": list(map(lambda skill: skill.to_dict(), self.skills)),

@ -4,7 +4,7 @@ from functools import wraps
from ki.auth import auth
from ki.handlers import update_profile as update_profile_handler
from ki.models import Language, Skill, Token, User
from ki.models import ContactType, Language, Skill, Token, User
from app import app
@ -116,6 +116,9 @@ def get_user_profile(user_id):
if profile is None:
return make_response({}, 404)
if not profile.visible and profile.user.id != g.user.id:
return make_response({}, 403)
return make_response({
"profile": profile.to_dict(),
})
@ -130,6 +133,12 @@ def update_profile(user_id):
return update_profile_handler(int(user_id))
@app.route("/contacttypes")
@token_auth
def get_contacttypes():
return handle_completion_request(ContactType, "contacttypes")
@app.route("/skills")
@token_auth
def get_skills():

@ -0,0 +1,40 @@
import unittest
from ki.test.ApiTest import ApiTest
class TestContactTypesEndpoint(ApiTest):
def test_skills_options(self):
response = self.client.options("/contacttypes")
self.assertEqual(response.status_code, 200)
self.assertIn("Access-Control-Allow-Origin", response.headers)
self.assertEqual(response.headers["Access-Control-Allow-Origin"], "*")
def test_get_contacttypes_unauthorised(self):
response = self.client.get("/contacttypes?search=m")
self.assertEqual(response.status_code, 401)
def test_get_contacttypes(self):
token = self.login("peter", "geheim")["token"]
response = self.client.get("/contacttypes?search=m", headers={"Authorization": "Bearer " + token})
self.assertEqual(response.status_code, 200)
self.assertEqual(
{
"contacttypes": [{
"id": 5,
"name": "Mastodon"
}, {
"id": 4,
"name": "Matrix"
}, {
"id": 2,
"name": "Mobiltelefon"
}]
}, response.json)
self.assertIn("Access-Control-Allow-Origin", response.headers)
self.assertEqual(response.headers["Access-Control-Allow-Origin"], "*")
if __name__ == "main":
unittest.main()

@ -30,6 +30,7 @@ class TestProfileEndpoint(ApiTest):
"pronouns": "Monsieur",
"volunteerwork": "ja",
"freetext": "Hallo",
"visible": True,
"address": {
"name": "Peeeda",
"street": "Bachstraße",
@ -42,7 +43,7 @@ class TestProfileEndpoint(ApiTest):
"contacts": [{
"id": 1,
"contacttype": {
"id": 1,
"id": 4,
"name": "Matrix"
},
"content": "@peeda:wtf-eg.de"
@ -92,6 +93,7 @@ class TestProfileEndpoint(ApiTest):
self.assertEqual("Monsieur", profile.pronouns)
self.assertEqual("ja", profile.volunteerwork)
self.assertEqual("Hallo", profile.freetext)
self.assertTrue(profile.visible)
address = profile.address
self.assertEqual(address.name, "Peeeda")
@ -137,6 +139,11 @@ class TestProfileEndpoint(ApiTest):
self.assertEqual(second_language.language_id, "es")
self.assertEqual(second_language.level, 2)
def test_get_profile_unauthorised(self):
response = self.client.get("/users/1/profile")
self.assertEqual(response.status_code, 401)
def test_get_profile(self):
login_data = {"username": "peter", "password": "geheim"}
login_response = self.client.post("/users/login", data=json.dumps(login_data), content_type="application/json")
@ -156,6 +163,7 @@ class TestProfileEndpoint(ApiTest):
"pronouns": "Herr Dr. Dr.",
"freetext": "Ich mag Kaffee",
"volunteerwork": "Gartenverein",
"visible": False,
"address": {
"additional": "Hinterhaus",
"city": "Bielefeld",
@ -171,7 +179,7 @@ class TestProfileEndpoint(ApiTest):
"id": 1,
"profile_id": 1,
"contacttype": {
"id": 1,
"id": 4,
"name": "Matrix"
},
"content": "@peter:wtf-eg.de"
@ -179,7 +187,7 @@ class TestProfileEndpoint(ApiTest):
"id": 2,
"profile_id": 1,
"contacttype": {
"id": 2,
"id": 1,
"name": "E-Mail"
},
"content": "peter@wtf-eg.de"

@ -1,8 +1,8 @@
"""Initial migration.
Revision ID: f95308aceda1
Revision ID: ebb2dd1fb371
Revises:
Create Date: 2021-06-20 19:11:47.086814
Create Date: 2021-07-02 16:20:18.160228
"""
from alembic import op
@ -10,7 +10,7 @@ import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = 'f95308aceda1'
revision = 'ebb2dd1fb371'
down_revision = None
branch_labels = None
depends_on = None
@ -34,6 +34,7 @@ def upgrade():
sa.Column('pronouns', sa.String(length=25), nullable=True),
sa.Column('volunteerwork', sa.String(length=4000), nullable=True),
sa.Column('freetext', sa.String(length=4000), nullable=True),
sa.Column('visible', sa.Boolean(), nullable=False),
sa.Column('created', sa.DateTime(), nullable=False),
sa.Column('updated', sa.DateTime(), nullable=False),
sa.PrimaryKeyConstraint('id'),