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

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 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): def seed(dev: bool):
seed_contacttypes()
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") logging.info("importing skills")
@ -47,16 +65,10 @@ def seed(dev: bool):
user=peter) user=peter)
db.session.add(peters_profile) db.session.add(peters_profile)
matrix_type = ContactType(name="Matrix") matrix_contact = Contact(profile=peters_profile, contacttype_id=4, content="@peter:wtf-eg.de")
db.session.add(matrix_type)
matrix_contact = Contact(profile=peters_profile, contacttype=matrix_type, content="@peter:wtf-eg.de")
db.session.add(matrix_contact) db.session.add(matrix_contact)
email_type = ContactType(name="E-Mail") email_contact = Contact(profile=peters_profile, contacttype_id=1, content="peter@wtf-eg.de")
db.session.add(email_type)
email_contact = Contact(profile=peters_profile, contacttype=email_type, content="peter@wtf-eg.de")
db.session.add(email_contact) db.session.add(email_contact)
peters_address = Address(name="Peter Nichtlustig", 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.pronouns = request.json.get("pronouns", "")
profile.volunteerwork = request.json.get("volunteerwork", "") profile.volunteerwork = request.json.get("volunteerwork", "")
profile.freetext = request.json.get("freetext", "") profile.freetext = request.json.get("freetext", "")
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", {}))

View File

@ -1,6 +1,6 @@
from datetime import datetime 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 sqlalchemy.orm import relationship
from app import db from app import db
@ -28,6 +28,7 @@ class Profile(db.Model):
pronouns = Column(String(25), default="") pronouns = Column(String(25), default="")
volunteerwork = Column(String(4000), default="") volunteerwork = Column(String(4000), default="")
freetext = Column(String(4000), default="") freetext = Column(String(4000), default="")
visible = Column(Boolean, nullable=False, default=False)
created = Column(DateTime, nullable=False, default=datetime.now) created = Column(DateTime, nullable=False, default=datetime.now)
updated = Column(DateTime, onupdate=datetime.now, 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, "pronouns": self.pronouns,
"volunteerwork": self.volunteerwork, "volunteerwork": self.volunteerwork,
"freetext": self.freetext, "freetext": self.freetext,
"visible": self.visible,
"address": self.address.to_dict(), "address": self.address.to_dict(),
"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)),

View File

@ -4,7 +4,7 @@ from functools import wraps
from ki.auth import auth from ki.auth import auth
from ki.handlers import update_profile as update_profile_handler 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 from app import app
@ -116,6 +116,9 @@ def get_user_profile(user_id):
if profile is None: if profile is None:
return make_response({}, 404) return make_response({}, 404)
if not profile.visible and profile.user.id != g.user.id:
return make_response({}, 403)
return make_response({ return make_response({
"profile": profile.to_dict(), "profile": profile.to_dict(),
}) })
@ -130,6 +133,12 @@ def update_profile(user_id):
return update_profile_handler(int(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") @app.route("/skills")
@token_auth @token_auth
def get_skills(): 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", "pronouns": "Monsieur",
"volunteerwork": "ja", "volunteerwork": "ja",
"freetext": "Hallo", "freetext": "Hallo",
"visible": True,
"address": { "address": {
"name": "Peeeda", "name": "Peeeda",
"street": "Bachstraße", "street": "Bachstraße",
@ -42,7 +43,7 @@ class TestProfileEndpoint(ApiTest):
"contacts": [{ "contacts": [{
"id": 1, "id": 1,
"contacttype": { "contacttype": {
"id": 1, "id": 4,
"name": "Matrix" "name": "Matrix"
}, },
"content": "@peeda:wtf-eg.de" "content": "@peeda:wtf-eg.de"
@ -92,6 +93,7 @@ class TestProfileEndpoint(ApiTest):
self.assertEqual("Monsieur", profile.pronouns) self.assertEqual("Monsieur", profile.pronouns)
self.assertEqual("ja", profile.volunteerwork) self.assertEqual("ja", profile.volunteerwork)
self.assertEqual("Hallo", profile.freetext) self.assertEqual("Hallo", profile.freetext)
self.assertTrue(profile.visible)
address = profile.address address = profile.address
self.assertEqual(address.name, "Peeeda") self.assertEqual(address.name, "Peeeda")
@ -137,6 +139,11 @@ class TestProfileEndpoint(ApiTest):
self.assertEqual(second_language.language_id, "es") self.assertEqual(second_language.language_id, "es")
self.assertEqual(second_language.level, 2) 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): def test_get_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")
@ -156,6 +163,7 @@ class TestProfileEndpoint(ApiTest):
"pronouns": "Herr Dr. Dr.", "pronouns": "Herr Dr. Dr.",
"freetext": "Ich mag Kaffee", "freetext": "Ich mag Kaffee",
"volunteerwork": "Gartenverein", "volunteerwork": "Gartenverein",
"visible": False,
"address": { "address": {
"additional": "Hinterhaus", "additional": "Hinterhaus",
"city": "Bielefeld", "city": "Bielefeld",
@ -171,7 +179,7 @@ class TestProfileEndpoint(ApiTest):
"id": 1, "id": 1,
"profile_id": 1, "profile_id": 1,
"contacttype": { "contacttype": {
"id": 1, "id": 4,
"name": "Matrix" "name": "Matrix"
}, },
"content": "@peter:wtf-eg.de" "content": "@peter:wtf-eg.de"
@ -179,7 +187,7 @@ class TestProfileEndpoint(ApiTest):
"id": 2, "id": 2,
"profile_id": 1, "profile_id": 1,
"contacttype": { "contacttype": {
"id": 2, "id": 1,
"name": "E-Mail" "name": "E-Mail"
}, },
"content": "peter@wtf-eg.de" "content": "peter@wtf-eg.de"

View File

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