Compare commits

..

1 Commits

Author SHA1 Message Date
f7bb86433b added script_location entry (it was missed in OSX environment) 2021-06-20 14:20:03 +02:00
7 changed files with 82 additions and 257 deletions

View File

@ -74,16 +74,6 @@ curl -s \
http://localhost:5000/users/login | jq
```
```
curl -s \
-D "/dev/stderr" \
-X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer 22e6c5fc-8a5a-440e-b1f4-018deb9fd24e" \
-d '{"pronouns": "Herr Dr. Dr."}' \
http://localhost:5000/users/1/profile | jq
```
```
curl -s \
-D "/dev/stderr" \

View File

@ -5,41 +5,28 @@ from app import app, db
from ki.models import User, Token
class UserWrongCredentialsException(Exception):
pass
class UserAllreadyLoggedInException(Exception):
pass
def auth(username, password):
auth_file_path = app.config["KI_DATA_DIR"] + "/auth.yml"
with open(auth_file_path, "r") as auth_file_stream:
users = yaml.safe_load(auth_file_stream)
try:
users = yaml.safe_load(auth_file_stream)
except yaml.YAMLError:
print('Could not parse auth.yml.')
try:
auth_user = users[username]
if auth_user["password"] != password:
raise UserWrongCredentialsException
except (UserWrongCredentialsException, KeyError):
print('Wrong username/password combination')
if username not in users:
return None
else:
user = User.query.filter(User.auth_id.__eq__(username)).first()
auth_user = users[username]
token = Token(token=str(uuid.uuid4()), user=user)
if auth_user["password"] != password:
return None
db.session.add(token)
db.session.commit()
user = User.query.filter(User.auth_id.__eq__(username)).first()
return token
if user is None:
user = User(nickname=username, auth_id=username)
db.session.add(user)
token = Token(token=str(uuid.uuid4()), user=user)
db.session.add(token)
db.session.commit()
return token

View File

@ -9,43 +9,25 @@ from app import db
class User(db.Model):
__tablename__ = "user"
id = Column(Integer, primary_key=True)
auth_id = Column(String(50), nullable=False, unique=True)
profile_id = Column(Integer, ForeignKey("profile.id"), nullable=True)
tokens = relationship("Token", uselist=False, back_populates="user")
profile = relationship("Profile", back_populates="user")
def to_dict(self):
return {"id": self.id}
class Profile(db.Model):
__tablename__ = "profile"
id = Column(Integer, primary_key=True)
nickname = Column(String(25), unique=True, nullable=False)
pronouns = Column(String(25), default="")
volunteerwork = Column(String(4000), default="")
freetext = Column(String(4000), default="")
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)
auth_id = Column(String(50), nullable=False, unique=True)
user = relationship("User", back_populates="profile", uselist=False)
contacts = relationship("Contact")
address = relationship("Address", uselist=False, back_populates="profile")
skills = relationship("ProfileSkill", back_populates="profile")
languages = relationship("ProfileLanguage", back_populates="profile")
address = relationship("Address", uselist=False, back_populates="user")
tokens = relationship("Token", uselist=False, back_populates="user")
skills = relationship("UserSkill", back_populates="user")
languages = relationship("UserLanguage", back_populates="user")
def to_dict(self):
return {
"nickname": self.nickname,
"pronouns": self.pronouns,
"volunteerwork": self.volunteerwork,
"freetext": self.freetext
"id": self.id,
"nickname": self.nickname
}
@ -63,11 +45,9 @@ class Contact(db.Model):
__tablename__ = "contact"
id = Column(Integer, primary_key=True)
profile_id = Column(Integer, ForeignKey("profile.id"), nullable=False)
profile = relationship("Profile", back_populates="contacts")
contacttype_id = Column(Integer,
ForeignKey("contacttype.id"),
nullable=False)
user_id = Column(Integer, ForeignKey("user.id"), nullable=False)
user = relationship("User", back_populates="contacts")
contacttype_id = Column(Integer, ForeignKey("contacttype.id"), nullable=False)
contacttype = relationship("ContactType")
content = Column(String(200), nullable=False)
@ -91,8 +71,8 @@ class Address(db.Model):
city = Column(String(25), default="")
country = Column(String(25), default="")
profile_id = Column(Integer, ForeignKey("profile.id"), nullable=False)
profile = relationship("Profile", back_populates="address")
user_id = Column(Integer, ForeignKey("user.id"), nullable=False)
user = relationship("User", back_populates="address")
class Skill(db.Model):
@ -101,21 +81,21 @@ class Skill(db.Model):
id = Column(Integer, primary_key=True)
name = Column(String(25), unique=True, nullable=False)
profiles = relationship("ProfileSkill", back_populates="skill")
users = relationship("UserSkill", back_populates="skill")
def to_dict(self):
return {"id": self.id, "name": self.name}
class ProfileSkill(db.Model):
__tablename__ = "profile_skill"
class UserSkill(db.Model):
__tablename__ = "user_skill"
profile_id = Column(Integer, ForeignKey("profile.id"), primary_key=True)
user_id = Column(Integer, ForeignKey("user.id"), primary_key=True)
skill_id = Column(Integer, ForeignKey("skill.id"), primary_key=True)
level = Column(SmallInteger, nullable=False)
profile = relationship("Profile", back_populates="skills")
skill = relationship("Skill", back_populates="profiles")
user = relationship("User", back_populates="skills")
skill = relationship("Skill", back_populates="users")
class Language(db.Model):
@ -124,18 +104,18 @@ class Language(db.Model):
id = Column(String(2), primary_key=True)
name = Column(String(25), nullable=False)
profiles = relationship("ProfileLanguage", back_populates="language")
users = relationship("UserLanguage", back_populates="language")
def to_dict(self):
return {"id": self.id, "name": self.name}
class ProfileLanguage(db.Model):
__tablename__ = "profile_language"
class UserLanguage(db.Model):
__tablename__ = "user_language"
profile_id = Column(Integer, ForeignKey("profile.id"), primary_key=True)
user_id = Column(Integer, ForeignKey("user.id"), primary_key=True)
language_id = Column(Integer, ForeignKey("language.id"), primary_key=True)
level = Column(SmallInteger, nullable=False)
profile = relationship("Profile", back_populates="languages")
language = relationship("Language", back_populates="profiles")
user = relationship("User", back_populates="languages")
language = relationship("Language", back_populates="users")

View File

@ -3,8 +3,8 @@ from flask import g, make_response, request, send_file
from functools import wraps
from ki.auth import auth
from ki.models import Language, Skill, Token, User, Profile
from app import app, db
from ki.models import Language, Skill, Token, User
from app import app
def token_auth(func):
@ -110,34 +110,7 @@ def get_user_profile(user_id):
if user is None:
return make_response({}, 404)
profile = user.profile
if profile is None:
return make_response({}, 404)
return make_response({"profile": profile.to_dict()})
@app.route("/users/<user_id>/profile", methods=["POST"])
def update_profile(user_id):
user = User.query.filter(User.id == int(user_id)).first()
if user is None:
return make_response({}, 404)
profile = user.profile
if (profile is None):
profile = Profile(user=user, nickname=user.auth_id)
db.session.add(profile)
profile.pronouns = request.json.get("pronouns", "")
profile.volunteerwork = request.json.get("volunteerwork", "")
profile.freetext = request.json.get("freetext", "")
db.session.commit()
return make_response(profile.to_dict(), 200)
return make_response({"user": user.to_dict()})
@app.route("/skills")

View File

@ -1,98 +0,0 @@
from alembic import command
import unittest
import json
from app import app, db, migrate
from ki.commands import seed
from ki.models import Profile, User
class TestProfileEndpoint(unittest.TestCase):
def setUp(self):
app.debug = True
app.config["TESTING"] = True
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///:memory:"
self.client = app.test_client()
with app.app_context():
config = migrate.get_config()
command.upgrade(config, "head")
seed()
def tearDown(self):
db.engine.dispose()
def test_create_profile(self):
user = User(auth_id="peter")
db.session.add(user)
db.session.commit()
login_data = {"username": "peter", "password": "geheim"}
login_response = self.client.post("/users/login",
data=json.dumps(login_data),
content_type="application/json")
self.assertEqual(login_response.status_code, 200)
self.assertIn("token", login_response.json)
data = {
"pronouns": "Herr Dr. Dr.",
"volunteerwork": "ja",
"freetext": "Hallo",
}
response = self.client.post("/users/1/profile",
data=json.dumps(data),
content_type="application/json",
headers={
"Authorization":
"Bearer " +
login_response.json["token"]
})
self.assertEqual(response.status_code, 200)
with app.app_context():
user = User.query.filter(User.id == 1).first()
profile = user.profile
self.assertEqual("Herr Dr. Dr.", profile.pronouns)
self.assertEqual("ja", profile.volunteerwork)
self.assertEqual("Hallo", profile.freetext)
def test_get_profile(self):
user = User(auth_id="peter")
db.session.add(user)
profile = Profile(user=user)
profile.nickname = "Popeter"
db.session.add(profile)
db.session.commit()
login_data = {"username": "peter", "password": "geheim"}
login_response = self.client.post("/users/login",
data=json.dumps(login_data),
content_type="application/json")
self.assertEqual(login_response.status_code, 200)
self.assertIn("token", login_response.json)
response = self.client.get("/users/1/profile",
headers={
"Authorization":
"Bearer " + login_response.json["token"]
})
self.assertEqual(response.status_code, 200)
self.assertEqual(
response.json, {
"profile": {
"freetext": "",
"nickname": "Popeter",
"pronouns": "",
"volunteerwork": ""
}
})
if __name__ == "main":
unittest.main()

View File

@ -7,7 +7,7 @@
# set to 'true' to run the environment during
# the 'revision' command, regardless of autogenerate
# revision_environment = false
script_location = .
# Logging configuration
[loggers]

View File

@ -1,8 +1,8 @@
"""Initial migration.
"""Initial migration
Revision ID: f95308aceda1
Revision ID: 575a8924eb16
Revises:
Create Date: 2021-06-20 19:11:47.086814
Create Date: 2021-06-12 13:18:24.903142
"""
from alembic import op
@ -10,7 +10,7 @@ import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = 'f95308aceda1'
revision = '575a8924eb16'
down_revision = None
branch_labels = None
depends_on = None
@ -28,7 +28,13 @@ def upgrade():
sa.Column('name', sa.String(length=25), nullable=False),
sa.PrimaryKeyConstraint('id')
)
op.create_table('profile',
op.create_table('skill',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('name', sa.String(length=25), nullable=False),
sa.PrimaryKeyConstraint('id'),
sa.UniqueConstraint('name')
)
op.create_table('user',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('nickname', sa.String(length=25), nullable=False),
sa.Column('pronouns', sa.String(length=25), nullable=True),
@ -36,15 +42,11 @@ def upgrade():
sa.Column('freetext', sa.String(length=4000), nullable=True),
sa.Column('created', sa.DateTime(), nullable=False),
sa.Column('updated', sa.DateTime(), nullable=False),
sa.Column('auth_id', sa.String(length=50), nullable=False),
sa.PrimaryKeyConstraint('id'),
sa.UniqueConstraint('auth_id'),
sa.UniqueConstraint('nickname')
)
op.create_table('skill',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('name', sa.String(length=25), nullable=False),
sa.PrimaryKeyConstraint('id'),
sa.UniqueConstraint('name')
)
op.create_table('address',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('name', sa.String(length=25), nullable=True),
@ -54,63 +56,54 @@ def upgrade():
sa.Column('postcode', sa.String(length=10), nullable=True),
sa.Column('city', sa.String(length=25), nullable=True),
sa.Column('country', sa.String(length=25), nullable=True),
sa.Column('profile_id', sa.Integer(), nullable=False),
sa.ForeignKeyConstraint(['profile_id'], ['profile.id'], ),
sa.Column('user_id', sa.Integer(), nullable=True),
sa.ForeignKeyConstraint(['user_id'], ['user.id'], ),
sa.PrimaryKeyConstraint('id')
)
op.create_table('contact',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('profile_id', sa.Integer(), nullable=False),
sa.Column('contacttype_id', sa.Integer(), nullable=False),
sa.Column('user_id', sa.Integer(), nullable=True),
sa.Column('contacttype_id', sa.Integer(), nullable=True),
sa.Column('content', sa.String(length=200), nullable=False),
sa.ForeignKeyConstraint(['contacttype_id'], ['contacttype.id'], ),
sa.ForeignKeyConstraint(['profile_id'], ['profile.id'], ),
sa.ForeignKeyConstraint(['user_id'], ['user.id'], ),
sa.PrimaryKeyConstraint('id')
)
op.create_table('profile_language',
sa.Column('profile_id', sa.Integer(), nullable=False),
sa.Column('language_id', sa.Integer(), nullable=False),
sa.Column('level', sa.SmallInteger(), nullable=False),
sa.ForeignKeyConstraint(['language_id'], ['language.id'], ),
sa.ForeignKeyConstraint(['profile_id'], ['profile.id'], ),
sa.PrimaryKeyConstraint('profile_id', 'language_id')
)
op.create_table('profile_skill',
sa.Column('profile_id', sa.Integer(), nullable=False),
sa.Column('skill_id', sa.Integer(), nullable=False),
sa.Column('level', sa.SmallInteger(), nullable=False),
sa.ForeignKeyConstraint(['profile_id'], ['profile.id'], ),
sa.ForeignKeyConstraint(['skill_id'], ['skill.id'], ),
sa.PrimaryKeyConstraint('profile_id', 'skill_id')
)
op.create_table('user',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('auth_id', sa.String(length=50), nullable=False),
sa.Column('profile_id', sa.Integer(), nullable=True),
sa.ForeignKeyConstraint(['profile_id'], ['profile.id'], ),
sa.PrimaryKeyConstraint('id'),
sa.UniqueConstraint('auth_id')
)
op.create_table('token',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('user_id', sa.Integer(), nullable=False),
sa.Column('user_id', sa.Integer(), nullable=True),
sa.Column('token', sa.String(length=36), nullable=False),
sa.ForeignKeyConstraint(['user_id'], ['user.id'], ),
sa.PrimaryKeyConstraint('id')
)
op.create_table('user_language',
sa.Column('user_id', sa.Integer(), nullable=False),
sa.Column('language_id', sa.Integer(), nullable=False),
sa.Column('level', sa.SmallInteger(), nullable=False),
sa.ForeignKeyConstraint(['language_id'], ['language.id'], ),
sa.ForeignKeyConstraint(['user_id'], ['user.id'], ),
sa.PrimaryKeyConstraint('user_id', 'language_id')
)
op.create_table('user_skill',
sa.Column('user_id', sa.Integer(), nullable=False),
sa.Column('skill_id', sa.Integer(), nullable=False),
sa.Column('level', sa.SmallInteger(), nullable=False),
sa.ForeignKeyConstraint(['skill_id'], ['skill.id'], ),
sa.ForeignKeyConstraint(['user_id'], ['user.id'], ),
sa.PrimaryKeyConstraint('user_id', 'skill_id')
)
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_table('user_skill')
op.drop_table('user_language')
op.drop_table('token')
op.drop_table('user')
op.drop_table('profile_skill')
op.drop_table('profile_language')
op.drop_table('contact')
op.drop_table('address')
op.drop_table('user')
op.drop_table('skill')
op.drop_table('profile')
op.drop_table('language')
op.drop_table('contacttype')
# ### end Alembic commands ###