feat: convert all uuid fields from str to proper UUID
ugh had to rewrite alembic migrations instead of just adding a new one.. will be good to be past this hiccup
This commit is contained in:
parent
6a471b87c2
commit
e1785ccfcc
|
@ -26,6 +26,8 @@ Auth Handler
|
||||||
This defines the default :term:`auth handler`.
|
This defines the default :term:`auth handler`.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import uuid as _uuid
|
||||||
|
|
||||||
from wuttjamaican.app import GenericHandler
|
from wuttjamaican.app import GenericHandler
|
||||||
|
|
||||||
|
|
||||||
|
@ -126,17 +128,28 @@ class AuthHandler(GenericHandler):
|
||||||
if not key:
|
if not key:
|
||||||
return
|
return
|
||||||
|
|
||||||
# try to match on Role.uuid
|
# maybe it is a uuid
|
||||||
role = session.get(model.Role, key)
|
if isinstance(key, _uuid.UUID):
|
||||||
if role:
|
role = session.get(model.Role, key)
|
||||||
return role
|
if role:
|
||||||
|
return role
|
||||||
|
|
||||||
# try to match on Role.name
|
else: # assuming it is a string
|
||||||
role = session.query(model.Role)\
|
|
||||||
.filter_by(name=key)\
|
# try to match on Role.uuid
|
||||||
.first()
|
try:
|
||||||
if role:
|
role = session.get(model.Role, _uuid.UUID(key))
|
||||||
return role
|
if role:
|
||||||
|
return role
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# try to match on Role.name
|
||||||
|
role = session.query(model.Role)\
|
||||||
|
.filter_by(name=key)\
|
||||||
|
.first()
|
||||||
|
if role:
|
||||||
|
return role
|
||||||
|
|
||||||
# try settings; if value then recurse
|
# try settings; if value then recurse
|
||||||
key = self.config.get(f'{self.appname}.role.{key}',
|
key = self.config.get(f'{self.appname}.role.{key}',
|
||||||
|
@ -178,21 +191,32 @@ class AuthHandler(GenericHandler):
|
||||||
if isinstance(obj, model.User):
|
if isinstance(obj, model.User):
|
||||||
return obj
|
return obj
|
||||||
|
|
||||||
# or maybe it is a string
|
# nb. these lookups require a db session
|
||||||
# (nb. these lookups require a db session)
|
if session:
|
||||||
if isinstance(obj, str) and session:
|
|
||||||
|
|
||||||
# try to match on User.uuid
|
# or maybe it is a uuid
|
||||||
user = session.get(model.User, obj)
|
if isinstance(obj, _uuid.UUID):
|
||||||
if user:
|
user = session.get(model.User, obj)
|
||||||
return user
|
if user:
|
||||||
|
return user
|
||||||
|
|
||||||
# try to match on User.username
|
# or maybe it is a string
|
||||||
user = session.query(model.User)\
|
elif isinstance(obj, str):
|
||||||
.filter(model.User.username == obj)\
|
|
||||||
.first()
|
# try to match on User.uuid
|
||||||
if user:
|
try:
|
||||||
return user
|
user = session.get(model.User, _uuid.UUID(obj))
|
||||||
|
if user:
|
||||||
|
return user
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# try to match on User.username
|
||||||
|
user = session.query(model.User)\
|
||||||
|
.filter(model.User.username == obj)\
|
||||||
|
.first()
|
||||||
|
if user:
|
||||||
|
return user
|
||||||
|
|
||||||
# nb. obj is presumbly another type of object, e.g. Person
|
# nb. obj is presumbly another type of object, e.g. Person
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ from typing import Sequence, Union
|
||||||
|
|
||||||
from alembic import op
|
from alembic import op
|
||||||
import sqlalchemy as sa
|
import sqlalchemy as sa
|
||||||
|
import wuttjamaican.db.util
|
||||||
|
|
||||||
|
|
||||||
# revision identifiers, used by Alembic.
|
# revision identifiers, used by Alembic.
|
||||||
|
@ -22,7 +23,7 @@ def upgrade() -> None:
|
||||||
|
|
||||||
# person
|
# person
|
||||||
op.create_table('person',
|
op.create_table('person',
|
||||||
sa.Column('uuid', sa.String(length=32), nullable=False),
|
sa.Column('uuid', wuttjamaican.db.util.UUID(), nullable=False),
|
||||||
sa.Column('full_name', sa.String(length=100), nullable=False),
|
sa.Column('full_name', sa.String(length=100), nullable=False),
|
||||||
sa.Column('first_name', sa.String(length=50), nullable=True),
|
sa.Column('first_name', sa.String(length=50), nullable=True),
|
||||||
sa.Column('middle_name', sa.String(length=50), nullable=True),
|
sa.Column('middle_name', sa.String(length=50), nullable=True),
|
||||||
|
@ -31,7 +32,7 @@ def upgrade() -> None:
|
||||||
)
|
)
|
||||||
|
|
||||||
# user
|
# user
|
||||||
op.add_column('user', sa.Column('person_uuid', sa.String(length=32), nullable=True))
|
op.add_column('user', sa.Column('person_uuid', wuttjamaican.db.util.UUID(), nullable=True))
|
||||||
op.create_foreign_key(op.f('fk_user_person_uuid_person'), 'user', 'person', ['person_uuid'], ['uuid'])
|
op.create_foreign_key(op.f('fk_user_person_uuid_person'), 'user', 'person', ['person_uuid'], ['uuid'])
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,66 +0,0 @@
|
||||||
"""convert uuid types
|
|
||||||
|
|
||||||
Revision ID: 6be0ed225f4d
|
|
||||||
Revises: 6bf900765500
|
|
||||||
Create Date: 2024-11-30 17:03:08.930050
|
|
||||||
|
|
||||||
"""
|
|
||||||
import uuid as _uuid
|
|
||||||
from typing import Sequence, Union
|
|
||||||
|
|
||||||
from alembic import op
|
|
||||||
import sqlalchemy as sa
|
|
||||||
import wuttjamaican.db.util
|
|
||||||
|
|
||||||
|
|
||||||
# revision identifiers, used by Alembic.
|
|
||||||
revision: str = '6be0ed225f4d'
|
|
||||||
down_revision: Union[str, None] = '6bf900765500'
|
|
||||||
branch_labels: Union[str, Sequence[str], None] = None
|
|
||||||
depends_on: Union[str, Sequence[str], None] = None
|
|
||||||
|
|
||||||
|
|
||||||
def upgrade() -> None:
|
|
||||||
|
|
||||||
# upgrade (convert uuid)
|
|
||||||
op.add_column('upgrade', sa.Column('uuid_true', wuttjamaican.db.util.UUID(), nullable=True))
|
|
||||||
upgrade = sa.sql.table('upgrade',
|
|
||||||
sa.sql.column('uuid'),
|
|
||||||
sa.sql.column('uuid_true'))
|
|
||||||
|
|
||||||
engine = op.get_bind()
|
|
||||||
cursor = engine.execute(upgrade.select())
|
|
||||||
for row in cursor.fetchall():
|
|
||||||
if row['uuid']:
|
|
||||||
uuid_true = _uuid.UUID(row['uuid'])
|
|
||||||
engine.execute(upgrade.update()\
|
|
||||||
.where(upgrade.c.uuid == row['uuid'])\
|
|
||||||
.values({'uuid_true': uuid_true}))
|
|
||||||
|
|
||||||
op.drop_constraint('pk_upgrade', 'upgrade', type_='primary')
|
|
||||||
op.drop_column('upgrade', 'uuid')
|
|
||||||
op.alter_column('upgrade', 'uuid_true', new_column_name='uuid')
|
|
||||||
op.create_primary_key('pk_upgrade', 'upgrade', ['uuid'])
|
|
||||||
|
|
||||||
|
|
||||||
def downgrade() -> None:
|
|
||||||
|
|
||||||
# upgrade (convert uuid)
|
|
||||||
op.add_column('upgrade', sa.Column('uuid_str', sa.VARCHAR(length=32), nullable=True))
|
|
||||||
upgrade = sa.sql.table('upgrade',
|
|
||||||
sa.sql.column('uuid'),
|
|
||||||
sa.sql.column('uuid_str'))
|
|
||||||
|
|
||||||
engine = op.get_bind()
|
|
||||||
cursor = engine.execute(upgrade.select())
|
|
||||||
for row in cursor.fetchall():
|
|
||||||
if row['uuid']:
|
|
||||||
uuid_str = row['uuid'].hex
|
|
||||||
engine.execute(upgrade.update()\
|
|
||||||
.where(upgrade.c.uuid == row['uuid'])\
|
|
||||||
.values({'uuid_str': uuid_str}))
|
|
||||||
|
|
||||||
op.drop_constraint('pk_upgrade', 'upgrade', type_='primary')
|
|
||||||
op.drop_column('upgrade', 'uuid')
|
|
||||||
op.alter_column('upgrade', 'uuid_str', new_column_name='uuid')
|
|
||||||
op.create_primary_key('pk_upgrade', 'upgrade', ['uuid'])
|
|
|
@ -9,6 +9,7 @@ from typing import Sequence, Union
|
||||||
|
|
||||||
from alembic import op
|
from alembic import op
|
||||||
import sqlalchemy as sa
|
import sqlalchemy as sa
|
||||||
|
import wuttjamaican.db.util
|
||||||
|
|
||||||
|
|
||||||
# revision identifiers, used by Alembic.
|
# revision identifiers, used by Alembic.
|
||||||
|
@ -22,7 +23,7 @@ def upgrade() -> None:
|
||||||
|
|
||||||
# role
|
# role
|
||||||
op.create_table('role',
|
op.create_table('role',
|
||||||
sa.Column('uuid', sa.String(length=32), nullable=False),
|
sa.Column('uuid', wuttjamaican.db.util.UUID(), nullable=False),
|
||||||
sa.Column('name', sa.String(length=100), nullable=False),
|
sa.Column('name', sa.String(length=100), nullable=False),
|
||||||
sa.Column('notes', sa.Text(), nullable=True),
|
sa.Column('notes', sa.Text(), nullable=True),
|
||||||
sa.PrimaryKeyConstraint('uuid'),
|
sa.PrimaryKeyConstraint('uuid'),
|
||||||
|
@ -31,7 +32,7 @@ def upgrade() -> None:
|
||||||
|
|
||||||
# user
|
# user
|
||||||
op.create_table('user',
|
op.create_table('user',
|
||||||
sa.Column('uuid', sa.String(length=32), nullable=False),
|
sa.Column('uuid', wuttjamaican.db.util.UUID(), nullable=False),
|
||||||
sa.Column('username', sa.String(length=25), nullable=False),
|
sa.Column('username', sa.String(length=25), nullable=False),
|
||||||
sa.Column('password', sa.String(length=60), nullable=True),
|
sa.Column('password', sa.String(length=60), nullable=True),
|
||||||
sa.Column('active', sa.Boolean(), nullable=False),
|
sa.Column('active', sa.Boolean(), nullable=False),
|
||||||
|
@ -41,7 +42,7 @@ def upgrade() -> None:
|
||||||
|
|
||||||
# permission
|
# permission
|
||||||
op.create_table('permission',
|
op.create_table('permission',
|
||||||
sa.Column('role_uuid', sa.String(length=32), nullable=False),
|
sa.Column('role_uuid', wuttjamaican.db.util.UUID(), nullable=False),
|
||||||
sa.Column('permission', sa.String(length=254), nullable=False),
|
sa.Column('permission', sa.String(length=254), nullable=False),
|
||||||
sa.ForeignKeyConstraint(['role_uuid'], ['role.uuid'], name=op.f('fk_permission_role_uuid_role')),
|
sa.ForeignKeyConstraint(['role_uuid'], ['role.uuid'], name=op.f('fk_permission_role_uuid_role')),
|
||||||
sa.PrimaryKeyConstraint('role_uuid', 'permission')
|
sa.PrimaryKeyConstraint('role_uuid', 'permission')
|
||||||
|
@ -49,9 +50,9 @@ def upgrade() -> None:
|
||||||
|
|
||||||
# user_x_role
|
# user_x_role
|
||||||
op.create_table('user_x_role',
|
op.create_table('user_x_role',
|
||||||
sa.Column('uuid', sa.String(length=32), nullable=False),
|
sa.Column('uuid', wuttjamaican.db.util.UUID(), nullable=False),
|
||||||
sa.Column('user_uuid', sa.String(length=32), nullable=False),
|
sa.Column('user_uuid', wuttjamaican.db.util.UUID(), nullable=False),
|
||||||
sa.Column('role_uuid', sa.String(length=32), nullable=False),
|
sa.Column('role_uuid', wuttjamaican.db.util.UUID(), nullable=False),
|
||||||
sa.ForeignKeyConstraint(['role_uuid'], ['role.uuid'], name=op.f('fk_user_x_role_role_uuid_role')),
|
sa.ForeignKeyConstraint(['role_uuid'], ['role.uuid'], name=op.f('fk_user_x_role_role_uuid_role')),
|
||||||
sa.ForeignKeyConstraint(['user_uuid'], ['user.uuid'], name=op.f('fk_user_x_role_user_uuid_user')),
|
sa.ForeignKeyConstraint(['user_uuid'], ['user.uuid'], name=op.f('fk_user_x_role_user_uuid_user')),
|
||||||
sa.PrimaryKeyConstraint('uuid')
|
sa.PrimaryKeyConstraint('uuid')
|
||||||
|
|
|
@ -10,6 +10,7 @@ from typing import Sequence, Union
|
||||||
from alembic import op
|
from alembic import op
|
||||||
import sqlalchemy as sa
|
import sqlalchemy as sa
|
||||||
from sqlalchemy.dialects import postgresql
|
from sqlalchemy.dialects import postgresql
|
||||||
|
import wuttjamaican.db.util
|
||||||
|
|
||||||
# revision identifiers, used by Alembic.
|
# revision identifiers, used by Alembic.
|
||||||
revision: str = 'ebd75b9feaa7'
|
revision: str = 'ebd75b9feaa7'
|
||||||
|
@ -23,15 +24,15 @@ def upgrade() -> None:
|
||||||
# upgrade
|
# upgrade
|
||||||
sa.Enum('PENDING', 'EXECUTING', 'SUCCESS', 'FAILURE', name='upgradestatus').create(op.get_bind())
|
sa.Enum('PENDING', 'EXECUTING', 'SUCCESS', 'FAILURE', name='upgradestatus').create(op.get_bind())
|
||||||
op.create_table('upgrade',
|
op.create_table('upgrade',
|
||||||
sa.Column('uuid', sa.String(length=32), nullable=False),
|
sa.Column('uuid', wuttjamaican.db.util.UUID(), nullable=False),
|
||||||
sa.Column('created', sa.DateTime(timezone=True), nullable=False),
|
sa.Column('created', sa.DateTime(timezone=True), nullable=False),
|
||||||
sa.Column('created_by_uuid', sa.String(length=32), nullable=False),
|
sa.Column('created_by_uuid', wuttjamaican.db.util.UUID(), nullable=False),
|
||||||
sa.Column('description', sa.String(length=255), nullable=False),
|
sa.Column('description', sa.String(length=255), nullable=False),
|
||||||
sa.Column('notes', sa.Text(), nullable=True),
|
sa.Column('notes', sa.Text(), nullable=True),
|
||||||
sa.Column('executing', sa.Boolean(), nullable=False),
|
sa.Column('executing', sa.Boolean(), nullable=False),
|
||||||
sa.Column('status', postgresql.ENUM('PENDING', 'EXECUTING', 'SUCCESS', 'FAILURE', name='upgradestatus', create_type=False), nullable=False),
|
sa.Column('status', postgresql.ENUM('PENDING', 'EXECUTING', 'SUCCESS', 'FAILURE', name='upgradestatus', create_type=False), nullable=False),
|
||||||
sa.Column('executed', sa.DateTime(timezone=True), nullable=True),
|
sa.Column('executed', sa.DateTime(timezone=True), nullable=True),
|
||||||
sa.Column('executed_by_uuid', sa.String(length=32), nullable=True),
|
sa.Column('executed_by_uuid', wuttjamaican.db.util.UUID(), nullable=True),
|
||||||
sa.Column('exit_code', sa.Integer(), nullable=True),
|
sa.Column('exit_code', sa.Integer(), nullable=True),
|
||||||
sa.ForeignKeyConstraint(['created_by_uuid'], ['user.uuid'], name=op.f('fk_upgrade_created_by_uuid_user')),
|
sa.ForeignKeyConstraint(['created_by_uuid'], ['user.uuid'], name=op.f('fk_upgrade_created_by_uuid_user')),
|
||||||
sa.ForeignKeyConstraint(['executed_by_uuid'], ['user.uuid'], name=op.f('fk_upgrade_executed_by_uuid_user')),
|
sa.ForeignKeyConstraint(['executed_by_uuid'], ['user.uuid'], name=op.f('fk_upgrade_executed_by_uuid_user')),
|
||||||
|
|
|
@ -30,7 +30,7 @@ import sqlalchemy as sa
|
||||||
from sqlalchemy import orm
|
from sqlalchemy import orm
|
||||||
from sqlalchemy.dialects.postgresql import UUID as PGUUID
|
from sqlalchemy.dialects.postgresql import UUID as PGUUID
|
||||||
|
|
||||||
from wuttjamaican.util import make_uuid
|
from wuttjamaican.util import make_true_uuid
|
||||||
|
|
||||||
|
|
||||||
# nb. this convention comes from upstream docs
|
# nb. this convention comes from upstream docs
|
||||||
|
@ -111,10 +111,10 @@ def uuid_column(*args, **kwargs):
|
||||||
Returns a UUID column for use as a table's primary key.
|
Returns a UUID column for use as a table's primary key.
|
||||||
"""
|
"""
|
||||||
if not args:
|
if not args:
|
||||||
args = (sa.String(length=32),)
|
args = (UUID(),)
|
||||||
kwargs.setdefault('primary_key', True)
|
kwargs.setdefault('primary_key', True)
|
||||||
kwargs.setdefault('nullable', False)
|
kwargs.setdefault('nullable', False)
|
||||||
kwargs.setdefault('default', make_uuid)
|
kwargs.setdefault('default', make_true_uuid)
|
||||||
return sa.Column(*args, **kwargs)
|
return sa.Column(*args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
@ -126,7 +126,7 @@ def uuid_fk_column(target_column, *args, **kwargs):
|
||||||
e.g. ``'user.uuid'``.
|
e.g. ``'user.uuid'``.
|
||||||
"""
|
"""
|
||||||
if not args:
|
if not args:
|
||||||
args = (sa.String(length=32), sa.ForeignKey(target_column))
|
args = (UUID(), sa.ForeignKey(target_column))
|
||||||
return sa.Column(*args, **kwargs)
|
return sa.Column(*args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -114,8 +114,7 @@ else:
|
||||||
def test_basic(self):
|
def test_basic(self):
|
||||||
column = mod.uuid_column()
|
column = mod.uuid_column()
|
||||||
self.assertIsInstance(column, sa.Column)
|
self.assertIsInstance(column, sa.Column)
|
||||||
self.assertIsInstance(column.type, sa.String)
|
self.assertIsInstance(column.type, mod.UUID)
|
||||||
self.assertEqual(column.type.length, 32)
|
|
||||||
|
|
||||||
|
|
||||||
class TestUUIDFKColumn(TestCase):
|
class TestUUIDFKColumn(TestCase):
|
||||||
|
@ -123,8 +122,7 @@ else:
|
||||||
def test_basic(self):
|
def test_basic(self):
|
||||||
column = mod.uuid_fk_column('foo.bar')
|
column = mod.uuid_fk_column('foo.bar')
|
||||||
self.assertIsInstance(column, sa.Column)
|
self.assertIsInstance(column, sa.Column)
|
||||||
self.assertIsInstance(column.type, sa.String)
|
self.assertIsInstance(column.type, mod.UUID)
|
||||||
self.assertEqual(column.type.length, 32)
|
|
||||||
|
|
||||||
|
|
||||||
class TestMakeTopoSortkey(DataTestCase):
|
class TestMakeTopoSortkey(DataTestCase):
|
||||||
|
|
|
@ -93,7 +93,7 @@ else:
|
||||||
self.config.usedb = True
|
self.config.usedb = True
|
||||||
role = self.handler.get_role(self.session, 'mykey')
|
role = self.handler.get_role(self.session, 'mykey')
|
||||||
self.assertIsNone(role)
|
self.assertIsNone(role)
|
||||||
setting = model.Setting(name='wutta.role.mykey', value=myrole.uuid)
|
setting = model.Setting(name='wutta.role.mykey', value=myrole.uuid.hex)
|
||||||
self.session.add(setting)
|
self.session.add(setting)
|
||||||
self.session.commit()
|
self.session.commit()
|
||||||
role = self.handler.get_role(self.session, 'mykey')
|
role = self.handler.get_role(self.session, 'mykey')
|
||||||
|
@ -117,6 +117,10 @@ else:
|
||||||
user = self.handler.get_user(myuser.uuid, session=self.session)
|
user = self.handler.get_user(myuser.uuid, session=self.session)
|
||||||
self.assertIs(user, myuser)
|
self.assertIs(user, myuser)
|
||||||
|
|
||||||
|
# match on User.uuid (str)
|
||||||
|
user = self.handler.get_user(myuser.uuid.hex, session=self.session)
|
||||||
|
self.assertIs(user, myuser)
|
||||||
|
|
||||||
# match on User.username
|
# match on User.username
|
||||||
user = self.handler.get_user(myuser.username, session=self.session)
|
user = self.handler.get_user(myuser.username, session=self.session)
|
||||||
self.assertIs(user, myuser)
|
self.assertIs(user, myuser)
|
||||||
|
|
Loading…
Reference in a new issue