source: main/waeup.cas/trunk/waeup/cas/db.py @ 11107

Last change on this file since 11107 was 10496, checked in by uli, 11 years ago

Allow users in service tickets to be NULL and give a proper ServiceTicket? representation.

File size: 4.1 KB
RevLine 
[10344]1# components to store tickets in a database
2# we use sqlite3
[10394]3import time
4from sqlalchemy import (
[10406]5    create_engine, Column, Integer, Float, String, Boolean, MetaData)
[10394]6from sqlalchemy.ext.declarative import declarative_base
7from sqlalchemy.orm import sessionmaker, scoped_session
[10419]8from sqlalchemy.pool import StaticPool
[10344]9
10
[10394]11Base = declarative_base()
12
13
14class ServiceTicket(Base):
15    __tablename__ = 'service_tickets'
16
17    id = Column(Integer, primary_key=True)
18    ticket = Column(String(255), nullable=False)
19    ts = Column(Float, nullable=False)
20    service = Column(String(2048), nullable=True)
[10496]21    user = Column(String(512), nullable=True)
[10406]22    sso = Column(Boolean, nullable=False, default=True)
[10394]23
[10406]24    def __init__(self, ticket, user, service=None, sso=True, timestamp=None):
[10394]25        if timestamp is None:
26            timestamp = time.time()
27        self.ticket = ticket
28        self.ts = timestamp
29        self.service = service
30        self.user = user
[10406]31        self.sso = sso
[10394]32
33    def __repr__(self):
[10496]34        return (
35            "ServiceTicket(ticket='%s', user='%s', service='%s', "
36            "sso=%s, timestamp=%s)" % (
37                self.ticket, self.user, self.service, self.sso, self.ts))
[10394]38
39
40class LoginTicket(Base):
41    __tablename__ = 'login_tickets'
42
43    ticket = Column(String(255), primary_key=True)
44    ts = Column(Float, nullable=False)
45
46    def __init__(self, ticket, timestamp=None):
47        if timestamp is None:
48            timestamp = time.time()
49        self.ticket = ticket
50        self.ts = timestamp
51
52    def __repr__(self):
53        return "LoginTicket('%s', %s)" % (self.ticket, self.ts)
54
55
56class TicketGrantingCookie(Base):
57    __tablename__ = 'ticket_granting_cookies'
58
59    value = Column(String(255), primary_key=True)
60    ts = Column(Float, nullable=False)
61
62    def __init__(self, value, timestamp=None):
63        if timestamp is None:
64            timestamp = time.time()
65        self.value = value
66        self.ts = timestamp
67
68    def __repr__(self):
69        return "TicketGrantingCookie('%s', %s)" % (self.value, self.ts)
70
71
72Session = scoped_session(sessionmaker())
73
74
75class DB(object):
76    """Abstract database to make data persistent.
77
78    Creates a database identified by `connection_string` if it does
79    not exist and initializes sessions.
80    """
81    @property
82    def session(self):
83        return Session
84
85    def __init__(self, connection_string):
[10419]86        args = {}
87        if connection_string in ('sqlite:///', 'sqlite:///:memory:'):
88            # make sure all threads access the same memory
89            args = dict(connect_args={'check_same_thread': False},
90                        poolclass=StaticPool)
91        self.engine = create_engine(connection_string, **args)
[10394]92        self.metadata = MetaData()
93        Base.metadata.create_all(self.engine)
94        Session.configure(bind=self.engine)
95
96    def add(self, item):
97        """Insert `item` into database.
98
99        `item` must be an instance of the database content types
100        defined in this module, normally some `Ticket` instance.
101        """
102        Session.add(item)
103        Session.commit()
104
105    def delete(self, item):
106        """Delete `item` from database.
107
108        `item must be an instance of the database content types
109        defined in this module, normally some `Ticket` instance.
110        """
111        Session.delete(item)
112        Session.commit()
113
114    def query(self, *args, **kw):
115        return Session.query(*args, **kw)
116
117
118class DBSessionContext(object):
119    """A context manager providing database sessions.
120
121    Creates a new (threadlocal) database session when entering and
122    tears down the session after leaving the context.
123
124    Tearing down includes committing transactions and closing the
125    connection.
126
127    Meant to be used as a wrapper for web request handlers, such, that
128    a session is created when a request comes in and released when
129    the response is ready to be delivered.
130
131    This context manager does *not* catch any exceptions.
132    """
133    def __enter__(self):
134        return Session()
135
136    def __exit__(self, *args, **kw):
137        if args or kw:
138            Session.rollback()
139        Session.remove()
140        return False
Note: See TracBrowser for help on using the repository browser.