Merge pull request 'visible, contacttypes' (#30) from feature-visible into main
continuous-integration/drone/push Build is passing Details

Reviewed-on: #30
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

View File

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

View File

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

View File

@ -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", {}))

View File

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

View File

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

View File

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

View File

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

View File

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