mirror of
https://gitlab.archlinux.org/archlinux/aurweb.git
synced 2025-02-03 10:43:03 +01:00
add aurweb.models.session.Session ORM database object
+ Added aurweb.util module. - Added make_random_string function. + Added aurweb.db.make_random_value function. - Takes a model and a column and introspects them to figure out the proper column length to create a random string for; then creates a unique string for that column. Signed-off-by: Kevin Morris <kevr@0cost.org>
This commit is contained in:
parent
adc9fccb7d
commit
1922e5380d
4 changed files with 129 additions and 1 deletions
42
aurweb/db.py
42
aurweb/db.py
|
@ -1,8 +1,10 @@
|
||||||
import math
|
import math
|
||||||
|
|
||||||
import aurweb.config
|
import aurweb.config
|
||||||
|
import aurweb.util
|
||||||
|
|
||||||
engine = None # See get_engine
|
# See get_engine.
|
||||||
|
engine = None
|
||||||
|
|
||||||
# ORM Session class.
|
# ORM Session class.
|
||||||
Session = None
|
Session = None
|
||||||
|
@ -10,6 +12,44 @@ Session = None
|
||||||
# Global ORM Session object.
|
# Global ORM Session object.
|
||||||
session = None
|
session = None
|
||||||
|
|
||||||
|
# Global introspected object memo.
|
||||||
|
introspected = dict()
|
||||||
|
|
||||||
|
|
||||||
|
def make_random_value(table: str, column: str):
|
||||||
|
""" Generate a unique, random value for a string column in a table.
|
||||||
|
|
||||||
|
This can be used to generate for example, session IDs that
|
||||||
|
align with the properties of the database column with regards
|
||||||
|
to size.
|
||||||
|
|
||||||
|
Internally, we use SQLAlchemy introspection to look at column
|
||||||
|
to decide which length to use for random string generation.
|
||||||
|
|
||||||
|
:return: A unique string that is not in the database
|
||||||
|
"""
|
||||||
|
global introspected
|
||||||
|
|
||||||
|
# Make sure column is converted to a string for memo interaction.
|
||||||
|
scolumn = str(column)
|
||||||
|
|
||||||
|
# If the target column is not yet introspected, store its introspection
|
||||||
|
# object into our global `introspected` memo.
|
||||||
|
if scolumn not in introspected:
|
||||||
|
from sqlalchemy import inspect
|
||||||
|
target_column = scolumn.split('.')[-1]
|
||||||
|
col = list(filter(lambda c: c.name == target_column,
|
||||||
|
inspect(table).columns))[0]
|
||||||
|
introspected[scolumn] = col
|
||||||
|
|
||||||
|
col = introspected.get(scolumn)
|
||||||
|
length = col.type.length
|
||||||
|
|
||||||
|
string = aurweb.util.make_random_string(length)
|
||||||
|
while session.query(table).filter(column == string).first():
|
||||||
|
string = aurweb.util.make_random_string(length)
|
||||||
|
return string
|
||||||
|
|
||||||
|
|
||||||
def query(model, *args, **kwargs):
|
def query(model, *args, **kwargs):
|
||||||
return session.query(model).filter(*args, **kwargs)
|
return session.query(model).filter(*args, **kwargs)
|
||||||
|
|
25
aurweb/models/session.py
Normal file
25
aurweb/models/session.py
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
from sqlalchemy import Column, Integer
|
||||||
|
from sqlalchemy.orm import backref, mapper, relationship
|
||||||
|
|
||||||
|
from aurweb.db import make_random_value
|
||||||
|
from aurweb.models.user import User
|
||||||
|
from aurweb.schema import Sessions
|
||||||
|
|
||||||
|
|
||||||
|
class Session:
|
||||||
|
UsersID = Column(Integer, nullable=True)
|
||||||
|
|
||||||
|
def __init__(self, **kwargs):
|
||||||
|
self.UsersID = kwargs.get("UsersID")
|
||||||
|
self.SessionID = kwargs.get("SessionID")
|
||||||
|
self.LastUpdateTS = kwargs.get("LastUpdateTS")
|
||||||
|
|
||||||
|
|
||||||
|
mapper(Session, Sessions, primary_key=[Sessions.c.SessionID], properties={
|
||||||
|
"User": relationship(User, backref=backref("session",
|
||||||
|
uselist=False))
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
def generate_unique_sid():
|
||||||
|
return make_random_value(Session, Session.SessionID)
|
7
aurweb/util.py
Normal file
7
aurweb/util.py
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
import random
|
||||||
|
import string
|
||||||
|
|
||||||
|
|
||||||
|
def make_random_string(length):
|
||||||
|
return ''.join(random.choices(string.ascii_lowercase +
|
||||||
|
string.digits, k=length))
|
56
test/test_session.py
Normal file
56
test/test_session.py
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
""" Test our Session model. """
|
||||||
|
from datetime import datetime
|
||||||
|
from unittest import mock
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from aurweb.models.account_type import AccountType
|
||||||
|
from aurweb.models.session import generate_unique_sid
|
||||||
|
from aurweb.testing import setup_test_db
|
||||||
|
from aurweb.testing.models import make_session, make_user
|
||||||
|
|
||||||
|
user, _session = None, None
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(autouse=True)
|
||||||
|
def setup():
|
||||||
|
from aurweb.db import session
|
||||||
|
|
||||||
|
global user, _session
|
||||||
|
|
||||||
|
setup_test_db("Users", "Sessions")
|
||||||
|
|
||||||
|
account_type = session.query(AccountType).filter(
|
||||||
|
AccountType.AccountType == "User").first()
|
||||||
|
user = make_user(Username="test", Email="test@example.org",
|
||||||
|
ResetKey="testReset", Passwd="testPassword",
|
||||||
|
AccountType=account_type)
|
||||||
|
_session = make_session(UsersID=user.ID, SessionID="testSession",
|
||||||
|
LastUpdateTS=datetime.utcnow())
|
||||||
|
|
||||||
|
|
||||||
|
def test_session():
|
||||||
|
assert _session.SessionID == "testSession"
|
||||||
|
assert _session.UsersID == user.ID
|
||||||
|
|
||||||
|
|
||||||
|
def test_session_user_association():
|
||||||
|
# Make sure that the Session user attribute is correct.
|
||||||
|
assert _session.User == user
|
||||||
|
|
||||||
|
|
||||||
|
def test_generate_unique_sid():
|
||||||
|
# Mock up aurweb.models.session.generate_sid by returning
|
||||||
|
# sids[i % 2] from 0 .. n. This will swap between each sid
|
||||||
|
# between each call.
|
||||||
|
sids = ["testSession", "realSession"]
|
||||||
|
i = 0
|
||||||
|
|
||||||
|
def mock_generate_sid(length):
|
||||||
|
nonlocal i
|
||||||
|
sid = sids[i % 2]
|
||||||
|
i += 1
|
||||||
|
return sid
|
||||||
|
|
||||||
|
with mock.patch("aurweb.util.make_random_string", mock_generate_sid):
|
||||||
|
assert generate_unique_sid() == "realSession"
|
Loading…
Add table
Reference in a new issue