upgrade-store-1.1-to-2.0 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. #!/usr/bin/env python
  2. # SQL Store Upgrade Script
  3. # for version 1.x to 2.0 of the OpenID library.
  4. # Doesn't depend on the openid library, so you can run this python
  5. # script to update databases for ruby or PHP as well.
  6. #
  7. # Testers note:
  8. #
  9. # A SQLite3 db with the 1.2 schema exists in
  10. # openid/test/data/openid-1.2-consumer-sqlitestore.db if you want something
  11. # to try upgrading.
  12. #
  13. # TODO:
  14. # * test data for mysql and postgresql.
  15. # * automated tests.
  16. import os
  17. import getpass
  18. import sys
  19. from optparse import OptionParser
  20. def askForPassword():
  21. return getpass.getpass("DB Password: ")
  22. def askForConfirmation(dbname,tablename):
  23. print """The table %s from the database %s will be dropped, and
  24. an empty table with the new nonce table schema will replace it."""%(
  25. tablename, dbname)
  26. return raw_input("Continue? ").lower().strip().startswith('y')
  27. def doSQLiteUpgrade(db_conn, nonce_table_name='oid_nonces'):
  28. cur = db_conn.cursor()
  29. cur.execute('DROP TABLE %s'%nonce_table_name)
  30. sql = """
  31. CREATE TABLE %s (
  32. server_url VARCHAR,
  33. timestamp INTEGER,
  34. salt CHAR(40),
  35. UNIQUE(server_url, timestamp, salt)
  36. );
  37. """%nonce_table_name
  38. cur.execute(sql)
  39. cur.close()
  40. def doMySQLUpgrade(db_conn, nonce_table_name='oid_nonces'):
  41. cur = db_conn.cursor()
  42. cur.execute('DROP TABLE %s'%nonce_table_name)
  43. sql = """
  44. CREATE TABLE %s (
  45. server_url BLOB,
  46. timestamp INTEGER,
  47. salt CHAR(40),
  48. PRIMARY KEY (server_url(255), timestamp, salt)
  49. )
  50. TYPE=InnoDB;
  51. """%nonce_table_name
  52. cur.execute(sql)
  53. cur.close()
  54. def doPostgreSQLUpgrade(db_conn, nonce_table_name='oid_nonces'):
  55. cur = db_conn.cursor()
  56. cur.execute('DROP TABLE %s'%nonce_table_name)
  57. sql = """
  58. CREATE TABLE %s (
  59. server_url VARCHAR(2047),
  60. timestamp INTEGER,
  61. salt CHAR(40),
  62. PRIMARY KEY (server_url, timestamp, salt)
  63. );
  64. """%nonce_table_name
  65. cur.execute(sql)
  66. cur.close()
  67. db_conn.commit()
  68. def main(argv=None):
  69. parser = OptionParser()
  70. parser.add_option("-u", "--user", dest="username",
  71. default=os.environ.get('USER'),
  72. help="User name to use to connect to the DB. "
  73. "Defaults to USER environment variable.")
  74. parser.add_option('-t', '--table', dest='tablename', default='oid_nonces',
  75. help='The name of the nonce table to drop and recreate. '
  76. ' Defaults to "oid_nonces", the default table name for '
  77. 'the openid stores.')
  78. parser.add_option('--mysql', dest='mysql_db_name',
  79. help='Upgrade a table from this MySQL database. '
  80. 'Requires username for database.')
  81. parser.add_option('--pg', '--postgresql', dest='postgres_db_name',
  82. help='Upgrade a table from this PostgreSQL database. '
  83. 'Requires username for database.')
  84. parser.add_option('--sqlite', dest='sqlite_db_name',
  85. help='Upgrade a table from this SQLite database file.')
  86. parser.add_option('--host', dest='db_host',
  87. default='localhost',
  88. help='Host on which to find MySQL or PostgreSQL DB.')
  89. (options, args) = parser.parse_args(argv)
  90. db_conn = None
  91. if options.sqlite_db_name:
  92. try:
  93. from pysqlite2 import dbapi2 as sqlite
  94. except ImportError:
  95. print "You must have pysqlite2 installed in your PYTHONPATH."
  96. return 1
  97. try:
  98. db_conn = sqlite.connect(options.sqlite_db_name)
  99. except Exception, e:
  100. print "Could not connect to SQLite database:", str(e)
  101. return 1
  102. if askForConfirmation(options.sqlite_db_name, options.tablename):
  103. doSQLiteUpgrade(db_conn, nonce_table_name=options.tablename)
  104. if options.postgres_db_name:
  105. if not options.username:
  106. print "A username is required to open a PostgreSQL Database."
  107. return 1
  108. password = askForPassword()
  109. try:
  110. import psycopg
  111. except ImportError:
  112. print "You need psycopg installed to update a postgres DB."
  113. return 1
  114. try:
  115. db_conn = psycopg.connect(database = options.postgres_db_name,
  116. user = options.username,
  117. host = options.db_host,
  118. password = password)
  119. except Exception, e:
  120. print "Could not connect to PostgreSQL database:", str(e)
  121. return 1
  122. if askForConfirmation(options.postgres_db_name, options.tablename):
  123. doPostgreSQLUpgrade(db_conn, nonce_table_name=options.tablename)
  124. if options.mysql_db_name:
  125. if not options.username:
  126. print "A username is required to open a MySQL Database."
  127. return 1
  128. password = askForPassword()
  129. try:
  130. import MySQLdb
  131. except ImportError:
  132. print "You must have MySQLdb installed to update a MySQL DB."
  133. return 1
  134. try:
  135. db_conn = MySQLdb.connect(options.db_host, options.username,
  136. password, options.mysql_db_name)
  137. except Exception, e:
  138. print "Could not connect to MySQL database:", str(e)
  139. return 1
  140. if askForConfirmation(options.mysql_db_name, options.tablename):
  141. doMySQLUpgrade(db_conn, nonce_table_name=options.tablename)
  142. if db_conn:
  143. db_conn.close()
  144. else:
  145. parser.print_help()
  146. return 0
  147. if __name__ == '__main__':
  148. retval = main()
  149. sys.exit(retval)