#!/usr/bin/env python
# SQL Store Upgrade Script
# for version 1.x to 2.0 of the OpenID library.
# Doesn't depend on the openid library, so you can run this python
# script to update databases for ruby or PHP as well.
#
# Testers note:
#
# A SQLite3 db with the 1.2 schema exists in
# openid/test/data/openid-1.2-consumer-sqlitestore.db if you want something
# to try upgrading.
#
# TODO:
# * test data for mysql and postgresql.
# * automated tests.
import os
import getpass
import sys
from optparse import OptionParser
def askForPassword():
return getpass.getpass("DB Password: ")
def askForConfirmation(dbname,tablename):
print """The table %s from the database %s will be dropped, and
an empty table with the new nonce table schema will replace it."""%(
tablename, dbname)
return raw_input("Continue? ").lower().strip().startswith('y')
def doSQLiteUpgrade(db_conn, nonce_table_name='oid_nonces'):
cur = db_conn.cursor()
cur.execute('DROP TABLE %s'%nonce_table_name)
sql = """
CREATE TABLE %s (
server_url VARCHAR,
timestamp INTEGER,
salt CHAR(40),
UNIQUE(server_url, timestamp, salt)
);
"""%nonce_table_name
cur.execute(sql)
cur.close()
def doMySQLUpgrade(db_conn, nonce_table_name='oid_nonces'):
cur = db_conn.cursor()
cur.execute('DROP TABLE %s'%nonce_table_name)
sql = """
CREATE TABLE %s (
server_url BLOB,
timestamp INTEGER,
salt CHAR(40),
PRIMARY KEY (server_url(255), timestamp, salt)
)
TYPE=InnoDB;
"""%nonce_table_name
cur.execute(sql)
cur.close()
def doPostgreSQLUpgrade(db_conn, nonce_table_name='oid_nonces'):
cur = db_conn.cursor()
cur.execute('DROP TABLE %s'%nonce_table_name)
sql = """
CREATE TABLE %s (
server_url VARCHAR(2047),
timestamp INTEGER,
salt CHAR(40),
PRIMARY KEY (server_url, timestamp, salt)
);
"""%nonce_table_name
cur.execute(sql)
cur.close()
db_conn.commit()
def main(argv=None):
parser = OptionParser()
parser.add_option("-u", "--user", dest="username",
default=os.environ.get('USER'),
help="User name to use to connect to the DB. "
"Defaults to USER environment variable.")
parser.add_option('-t', '--table', dest='tablename', default='oid_nonces',
help='The name of the nonce table to drop and recreate. '
' Defaults to "oid_nonces", the default table name for '
'the openid stores.')
parser.add_option('--mysql', dest='mysql_db_name',
help='Upgrade a table from this MySQL database. '
'Requires username for database.')
parser.add_option('--pg', '--postgresql', dest='postgres_db_name',
help='Upgrade a table from this PostgreSQL database. '
'Requires username for database.')
parser.add_option('--sqlite', dest='sqlite_db_name',
help='Upgrade a table from this SQLite database file.')
parser.add_option('--host', dest='db_host',
default='localhost',
help='Host on which to find MySQL or PostgreSQL DB.')
(options, args) = parser.parse_args(argv)
db_conn = None
if options.sqlite_db_name:
try:
from pysqlite2 import dbapi2 as sqlite
except ImportError:
print "You must have pysqlite2 installed in your PYTHONPATH."
return 1
try:
db_conn = sqlite.connect(options.sqlite_db_name)
except Exception, e:
print "Could not connect to SQLite database:", str(e)
return 1
if askForConfirmation(options.sqlite_db_name, options.tablename):
doSQLiteUpgrade(db_conn, nonce_table_name=options.tablename)
if options.postgres_db_name:
if not options.username:
print "A username is required to open a PostgreSQL Database."
return 1
password = askForPassword()
try:
import psycopg
except ImportError:
print "You need psycopg installed to update a postgres DB."
return 1
try:
db_conn = psycopg.connect(database = options.postgres_db_name,
user = options.username,
host = options.db_host,
password = password)
except Exception, e:
print "Could not connect to PostgreSQL database:", str(e)
return 1
if askForConfirmation(options.postgres_db_name, options.tablename):
doPostgreSQLUpgrade(db_conn, nonce_table_name=options.tablename)
if options.mysql_db_name:
if not options.username:
print "A username is required to open a MySQL Database."
return 1
password = askForPassword()
try:
import MySQLdb
except ImportError:
print "You must have MySQLdb installed to update a MySQL DB."
return 1
try:
db_conn = MySQLdb.connect(options.db_host, options.username,
password, options.mysql_db_name)
except Exception, e:
print "Could not connect to MySQL database:", str(e)
return 1
if askForConfirmation(options.mysql_db_name, options.tablename):
doMySQLUpgrade(db_conn, nonce_table_name=options.tablename)
if db_conn:
db_conn.close()
else:
parser.print_help()
return 0
if __name__ == '__main__':
retval = main()
sys.exit(retval)
|