From bd54344ddc24d518c05c5f508cc0af98d8e6f80e Mon Sep 17 00:00:00 2001 From: kaiyou <pierre@jaury.eu> Date: Tue, 10 Sep 2019 22:26:20 +0200 Subject: [PATCH] Update the database models --- migrations/script.py.mako | 4 +- migrations/versions/a95b3a78f983_.py | 68 ++++++++++++++++++++++++ trurt/models.py | 78 ++++++++++++++++------------ 3 files changed, 115 insertions(+), 35 deletions(-) create mode 100644 migrations/versions/a95b3a78f983_.py diff --git a/migrations/script.py.mako b/migrations/script.py.mako index 2c015630..a78eb7db 100644 --- a/migrations/script.py.mako +++ b/migrations/script.py.mako @@ -1,15 +1,13 @@ -"""${message} +""" ${message} Revision ID: ${up_revision} Revises: ${down_revision | comma,n} Create Date: ${create_date} - """ from alembic import op import sqlalchemy as sa ${imports if imports else ""} -# revision identifiers, used by Alembic. revision = ${repr(up_revision)} down_revision = ${repr(down_revision)} branch_labels = ${repr(branch_labels)} diff --git a/migrations/versions/a95b3a78f983_.py b/migrations/versions/a95b3a78f983_.py new file mode 100644 index 00000000..a53916a7 --- /dev/null +++ b/migrations/versions/a95b3a78f983_.py @@ -0,0 +1,68 @@ +""" Create initial schemas + +Revision ID: a95b3a78f983 +Revises: +Create Date: 2019-09-10 21:33:43.332000 +""" + +from alembic import op +import sqlalchemy as sa + + +revision = 'a95b3a78f983' +down_revision = None +branch_labels = None +depends_on = None + + +def upgrade(): + op.create_table('service', + sa.Column('spn', sa.String(length=255), nullable=True), + sa.Column('protocol', sa.String(length=25), nullable=True), + sa.Column('config', sa.String(), nullable=True), + sa.Column('id', sa.Integer(), nullable=False), + sa.Column('created_at', sa.Date(), nullable=False), + sa.Column('updated_at', sa.Date(), nullable=True), + sa.Column('comment', sa.String(length=255), nullable=True), + sa.PrimaryKeyConstraint('id'), + sa.UniqueConstraint('spn') + ) + op.create_table('user', + sa.Column('username', sa.String(length=255), nullable=False), + sa.Column('id', sa.Integer(), nullable=False), + sa.Column('created_at', sa.Date(), nullable=False), + sa.Column('updated_at', sa.Date(), nullable=True), + sa.Column('comment', sa.String(length=255), nullable=True), + sa.PrimaryKeyConstraint('id'), + sa.UniqueConstraint('username') + ) + op.create_table('auth', + sa.Column('user_id', sa.Integer(), nullable=True), + sa.Column('value', sa.String(), nullable=True), + sa.Column('extra', sa.String(), nullable=True), + sa.Column('id', sa.Integer(), nullable=False), + sa.Column('created_at', sa.Date(), nullable=False), + sa.Column('updated_at', sa.Date(), nullable=True), + sa.Column('comment', sa.String(length=255), nullable=True), + sa.ForeignKeyConstraint(['user_id'], ['user.id'], ), + sa.PrimaryKeyConstraint('id') + ) + op.create_table('profile', + sa.Column('user_id', sa.Integer(), nullable=True), + sa.Column('service_id', sa.Integer(), nullable=True), + sa.Column('username', sa.String(length=255), nullable=False), + sa.Column('id', sa.Integer(), nullable=False), + sa.Column('created_at', sa.Date(), nullable=False), + sa.Column('updated_at', sa.Date(), nullable=True), + sa.Column('comment', sa.String(length=255), nullable=True), + sa.ForeignKeyConstraint(['service_id'], ['service.id'], ), + sa.ForeignKeyConstraint(['user_id'], ['user.id'], ), + sa.PrimaryKeyConstraint('id') + ) + + +def downgrade(): + op.drop_table('profile') + op.drop_table('auth') + op.drop_table('user') + op.drop_table('service') diff --git a/trurt/models.py b/trurt/models.py index d702a739..af1dca26 100644 --- a/trurt/models.py +++ b/trurt/models.py @@ -1,16 +1,40 @@ -from sqlalchemy.ext import declarative from passlib import context, hash -from datetime import datetime, date from flask import current_app as app +from sqlalchemy.ext import declarative +from datetime import date import flask_sqlalchemy import sqlalchemy -import time -import os -import glob -db = flask_sqlalchemy.SQLAlchemy() +class Base(flask_sqlalchemy.Model): + """ Base class for all models + """ + metadata = sqlalchemy.schema.MetaData( + naming_convention={ + "fk": "%(table_name)s_%(column_0_name)s_fkey", + "pk": "%(table_name)s_pkey" + } + ) + + @declarative.declared_attr + def id(cls): + return sqlalchemy.Column(sqlalchemy.Integer(), primary_key=True) + + @declarative.declared_attr + def created_at(cls): + return sqlalchemy.Column(sqlalchemy.Date, nullable=False, default=date.today) + + @declarative.declared_attr + def updated_at(cls): + return sqlalchemy.Column(sqlalchemy.Date, nullable=True, onupdate=date.today) + + @declarative.declared_attr + def comment(cls): + return sqlalchemy.Column(sqlalchemy.String(255), nullable=True) + + +db = flask_sqlalchemy.SQLAlchemy(model_class=Base) class JSONEncoded(db.TypeDecorator): @@ -26,38 +50,19 @@ class JSONEncoded(db.TypeDecorator): return json.loads(value) if value else None -class Base(db.Model): - """ Base class for all models - """ - - __abstract__ = True - - metadata = sqlalchemy.schema.MetaData( - naming_convention={ - "fk": "%(table_name)s_%(column_0_name)s_fkey", - "pk": "%(table_name)s_pkey" - } - ) - - id = db.Column(db.Integer(), primary_key=True) - created_at = db.Column(db.Date, nullable=False, default=date.today) - updated_at = db.Column(db.Date, nullable=True, onupdate=date.today) - comment = db.Column(db.String(255), nullable=True) - - -class User(Base): +class User(db.Model): """ A user is the local representation of an authenticated person. """ __tablename__ = "user" username = db.Column(db.String(255), nullable=False, unique=True) - # Flask-login attributes is_authenticated = True is_active = True is_anonymous = False + @classmethod def get(cls, id): return cls.query.get(id) @@ -65,12 +70,12 @@ class User(Base): return self.id -class Auth(Base): +class Auth(db.Model): """ An authenticator is a method to authenticate a user. """ __tablename__ = "auth" - user_username = db.Column(db.Integer(), db.ForeignKey(User.id)) + user_id = db.Column(db.Integer(), db.ForeignKey(User.id)) user = db.relationship(User, backref=db.backref('auths', cascade='all, delete-orphan')) # TODO: support multiple authentication realms, therefore more than @@ -78,8 +83,14 @@ class Auth(Base): value = db.Column(db.String) extra = db.Column(JSONEncoded) + def set_password(self, password): + self.value = hash.pbkdf2_sha256.hash(password) + + def check_password(self, password): + return hash.pbkdf2_sha256.verify(password, self.password) -class Service(Base): + +class Service(db.Model): """ A service is a client application (SP or RP typically). """ __tablename__ = "service" @@ -89,13 +100,16 @@ class Service(Base): config = db.Column(JSONEncoded) -class Profile(Base): +class Profile(db.Model): """ A profile is a user instance for a given service. """ __tablename__ = "profile" - username = db.Column(db.String(255), nullable=False) + user_id = db.Column(db.Integer(), db.ForeignKey(User.id)) + service_id = db.Column(db.Integer(), db.ForeignKey(Service.id)) user = db.relationship(User, backref=db.backref('profiles', cascade='all, delete-orphan')) service = db.relationship(Service, backref=db.backref('profiles', cascade='all, delete-orphan')) + + username = db.Column(db.String(255), nullable=False) -- GitLab