Commit 1922e538 authored by Kevin Morris's avatar Kevin Morris
Browse files

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's avatarKevin Morris <>
parent adc9fccb
import math
import aurweb.config
import aurweb.util
engine = None # See get_engine
# See get_engine.
engine = None
# ORM Session class.
Session = None
......@@ -10,6 +12,44 @@ Session = None
# Global ORM Session object.
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: == target_column,
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):
return session.query(model).filter(*args, **kwargs)
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",
def generate_unique_sid():
return make_random_value(Session, Session.SessionID)
import random
import string
def make_random_string(length):
return ''.join(random.choices(string.ascii_lowercase +
string.digits, k=length))
""" 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
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="",
ResetKey="testReset", Passwd="testPassword",
_session = make_session(UsersID=user.ID, SessionID="testSession",
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"
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment