##// END OF EJS Templates
Fixed dbmigrate issues.
marcink -
r907:2f83756f beta
parent child Browse files
Show More
@@ -1,494 +1,499 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 rhodecode.lib.db_manage
4 4 ~~~~~~~~~~~~~~~~~~~~~~~
5 5
6 6 Database creation, and setup module for RhodeCode. Used for creation
7 7 of database as well as for migration operations
8 8
9 9 :created_on: Apr 10, 2010
10 10 :author: marcink
11 11 :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
12 12 :license: GPLv3, see COPYING for more details.
13 13 """
14 14 # This program is free software; you can redistribute it and/or
15 15 # modify it under the terms of the GNU General Public License
16 16 # as published by the Free Software Foundation; version 2
17 17 # of the License or (at your opinion) any later version of the license.
18 18 #
19 19 # This program is distributed in the hope that it will be useful,
20 20 # but WITHOUT ANY WARRANTY; without even the implied warranty of
21 21 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 22 # GNU General Public License for more details.
23 23 #
24 24 # You should have received a copy of the GNU General Public License
25 25 # along with this program; if not, write to the Free Software
26 26 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
27 27 # MA 02110-1301, USA.
28 28
29 29 import os
30 30 import sys
31 31 import uuid
32 32 import logging
33 33 from os.path import dirname as dn, join as jn
34 34
35 35 from rhodecode import __dbversion__
36 36 from rhodecode.model import meta
37 37
38 38 from rhodecode.lib.auth import get_crypt_password
39 39 from rhodecode.lib.utils import ask_ok
40 40 from rhodecode.model import init_model
41 41 from rhodecode.model.db import User, Permission, RhodeCodeUi, RhodeCodeSettings, \
42 42 UserToPerm, DbMigrateVersion
43 43
44 44 from sqlalchemy.engine import create_engine
45 45
46 46 log = logging.getLogger(__name__)
47 47
48 48 class DbManage(object):
49 49 def __init__(self, log_sql, dbconf, root, tests=False):
50 50 self.dbname = dbconf.split('/')[-1]
51 51 self.tests = tests
52 52 self.root = root
53 53 self.dburi = dbconf
54 engine = create_engine(self.dburi, echo=log_sql)
54 self.log_sql = log_sql
55 self.db_exists = False
56 self.init_db()
57
58 def init_db(self):
59 engine = create_engine(self.dburi, echo=self.log_sql)
55 60 init_model(engine)
56 61 self.sa = meta.Session()
57 self.db_exists = False
58 62
59 63 def check_for_db(self, override):
60 64 db_path = jn(self.root, self.dbname)
61 65 if self.dburi.startswith('sqlite'):
62 66 log.info('checking for existing db in %s', db_path)
63 67 if os.path.isfile(db_path):
64 68
65 69 self.db_exists = True
66 70 if not override:
67 71 raise Exception('database already exists')
68 72
69 73 def create_tables(self, override=False):
70 74 """Create a auth database
71 75 """
72 76
73 77 self.check_for_db(override)
74 78 if self.db_exists:
75 79 log.info("database exist and it's going to be destroyed")
76 80 if self.tests:
77 81 destroy = True
78 82 else:
79 83 destroy = ask_ok('Are you sure to destroy old database ? [y/n]')
80 84 if not destroy:
81 85 sys.exit()
82 86 if self.db_exists and destroy:
83 87 os.remove(jn(self.root, self.dbname))
84 88 checkfirst = not override
85 89 meta.Base.metadata.create_all(checkfirst=checkfirst)
86 90 log.info('Created tables for %s', self.dbname)
87 91
88 92
89 93
90 94 def set_db_version(self):
91 95 try:
92 96 ver = DbMigrateVersion()
93 97 ver.version = __dbversion__
94 98 ver.repository_id = 'rhodecode_db_migrations'
95 99 ver.repository_path = 'versions'
96 100 self.sa.add(ver)
97 101 self.sa.commit()
98 102 except:
99 103 self.sa.rollback()
100 104 raise
101 105 log.info('db version set to: %s', __dbversion__)
102 106
103 107
104 108 def upgrade(self):
105 109 """Upgrades given database schema to given revision following
106 110 all needed steps, to perform the upgrade
107 111
108 112 """
109 113
110 114 from rhodecode.lib.dbmigrate.migrate.versioning import api
111 115 from rhodecode.lib.dbmigrate.migrate.exceptions import \
112 116 DatabaseNotControlledError
113 117
114 118 upgrade = ask_ok('You are about to perform database upgrade, make '
115 119 'sure You backed up your database before. '
116 120 'Continue ? [y/n]')
117 121 if not upgrade:
118 122 sys.exit('Nothing done')
119 123
120 124 repository_path = jn(dn(dn(dn(os.path.realpath(__file__)))),
121 125 'rhodecode/lib/dbmigrate')
122 126 db_uri = self.dburi
123 127
124 128 try:
125 129 curr_version = api.db_version(db_uri, repository_path)
126 130 msg = ('Found current database under version'
127 131 ' control with version %s' % curr_version)
128 132
129 133 except (RuntimeError, DatabaseNotControlledError), e:
130 134 curr_version = 1
131 135 msg = ('Current database is not under version control. Setting'
132 136 ' as version %s' % curr_version)
133 137 api.version_control(db_uri, repository_path, curr_version)
134 138
135 139 print (msg)
136 140
137 141 if curr_version == __dbversion__:
138 142 sys.exit('This database is already at the newest version')
139 143
140 144 #======================================================================
141 145 # UPGRADE STEPS
142 146 #======================================================================
143 147 class UpgradeSteps(object):
144 148 """Those steps follow schema versions so for example schema
145 149 for example schema with seq 002 == step_2 and so on.
146 150 """
147 151
148 152 def __init__(self, klass):
149 153 self.klass = klass
150 154
151 155 def step_0(self):
152 156 #step 0 is the schema upgrade, and than follow proper upgrades
153 157 print ('attempting to do database upgrade to version %s' \
154 158 % __dbversion__)
155 159 api.upgrade(db_uri, repository_path, __dbversion__)
156 160 print ('Schema upgrade completed')
157 161
158 162 def step_1(self):
159 163 pass
160 164
161 165 def step_2(self):
162 166 print ('Patching repo paths for newer version of RhodeCode')
163 167 self.klass.fix_repo_paths()
164 168
165 169 print ('Patching default user of RhodeCode')
166 170 self.klass.fix_default_user()
167 171
168 172 log.info('Changing ui settings')
169 173 self.klass.create_ui_settings()
170 174
171 175 def step_3(self):
172 176 print ('Adding additional settings into RhodeCode db')
173 177 self.klass.fix_settings()
174 178
175 179 upgrade_steps = [0] + range(curr_version + 1, __dbversion__ + 1)
176 180
177 181 #CALL THE PROPER ORDER OF STEPS TO PERFORM FULL UPGRADE
178 182 for step in upgrade_steps:
179 183 print ('performing upgrade step %s' % step)
180 184 callable = getattr(UpgradeSteps(self), 'step_%s' % step)()
181 185
182 186
183 187
184 188 def fix_repo_paths(self):
185 189 """Fixes a old rhodecode version path into new one without a '*'
186 190 """
187 191
188 192 paths = self.sa.query(RhodeCodeUi)\
189 193 .filter(RhodeCodeUi.ui_key == '/')\
190 194 .scalar()
191 195
192 196 paths.ui_value = paths.ui_value.replace('*', '')
193 197
194 198 try:
195 199 self.sa.add(paths)
196 200 self.sa.commit()
197 201 except:
198 202 self.sa.rollback()
199 203 raise
200 204
201 205 def fix_default_user(self):
202 206 """Fixes a old default user with some 'nicer' default values,
203 207 used mostly for anonymous access
204 208 """
205 209 def_user = self.sa.query(User)\
206 210 .filter(User.username == 'default')\
207 211 .one()
208 212
209 213 def_user.name = 'Anonymous'
210 214 def_user.lastname = 'User'
211 215 def_user.email = 'anonymous@rhodecode.org'
212 216
213 217 try:
214 218 self.sa.add(def_user)
215 219 self.sa.commit()
216 220 except:
217 221 self.sa.rollback()
218 222 raise
219 223
220 224 def fix_settings(self):
221 225 """Fixes rhodecode settings adds ga_code key for google analytics
222 226 """
223 227
224 228 hgsettings3 = RhodeCodeSettings('ga_code', '')
229
225 230 try:
226 231 self.sa.add(hgsettings3)
227 232 self.sa.commit()
228 233 except:
229 234 self.sa.rollback()
230 235 raise
231 236
232 237 def admin_prompt(self, second=False):
233 238 if not self.tests:
234 239 import getpass
235 240
236 241
237 242 def get_password():
238 243 password = getpass.getpass('Specify admin password (min 6 chars):')
239 244 confirm = getpass.getpass('Confirm password:')
240 245
241 246 if password != confirm:
242 247 log.error('passwords mismatch')
243 248 return False
244 249 if len(password) < 6:
245 250 log.error('password is to short use at least 6 characters')
246 251 return False
247 252
248 253 return password
249 254
250 255 username = raw_input('Specify admin username:')
251 256
252 257 password = get_password()
253 258 if not password:
254 259 #second try
255 260 password = get_password()
256 261 if not password:
257 262 sys.exit()
258 263
259 264 email = raw_input('Specify admin email:')
260 265 self.create_user(username, password, email, True)
261 266 else:
262 267 log.info('creating admin and regular test users')
263 268 self.create_user('test_admin', 'test12', 'test_admin@mail.com', True)
264 269 self.create_user('test_regular', 'test12', 'test_regular@mail.com', False)
265 270 self.create_user('test_regular2', 'test12', 'test_regular2@mail.com', False)
266 271
267 272 def create_ui_settings(self):
268 273 """Creates ui settings, fills out hooks
269 274 and disables dotencode
270 275
271 276 """
272 277 #HOOKS
273 278 hooks1_key = 'changegroup.update'
274 279 hooks1_ = self.sa.query(RhodeCodeUi)\
275 280 .filter(RhodeCodeUi.ui_key == hooks1_key).scalar()
276 281
277 282 hooks1 = RhodeCodeUi() if hooks1_ is None else hooks1_
278 283 hooks1.ui_section = 'hooks'
279 284 hooks1.ui_key = hooks1_key
280 285 hooks1.ui_value = 'hg update >&2'
281 286 hooks1.ui_active = False
282 287
283 288 hooks2_key = 'changegroup.repo_size'
284 289 hooks2_ = self.sa.query(RhodeCodeUi)\
285 290 .filter(RhodeCodeUi.ui_key == hooks2_key).scalar()
286 291
287 292 hooks2 = RhodeCodeUi() if hooks2_ is None else hooks2_
288 293 hooks2.ui_section = 'hooks'
289 294 hooks2.ui_key = hooks2_key
290 295 hooks2.ui_value = 'python:rhodecode.lib.hooks.repo_size'
291 296
292 297 hooks3 = RhodeCodeUi()
293 298 hooks3.ui_section = 'hooks'
294 299 hooks3.ui_key = 'pretxnchangegroup.push_logger'
295 300 hooks3.ui_value = 'python:rhodecode.lib.hooks.log_push_action'
296 301
297 302 hooks4 = RhodeCodeUi()
298 303 hooks4.ui_section = 'hooks'
299 304 hooks4.ui_key = 'preoutgoing.pull_logger'
300 305 hooks4.ui_value = 'python:rhodecode.lib.hooks.log_pull_action'
301 306
302 307 #For mercurial 1.7 set backward comapatibility with format
303 308 dotencode_disable = RhodeCodeUi()
304 309 dotencode_disable.ui_section = 'format'
305 310 dotencode_disable.ui_key = 'dotencode'
306 311 dotencode_disable.ui_value = 'false'
307 312
308 313 try:
309 314 self.sa.add(hooks1)
310 315 self.sa.add(hooks2)
311 316 self.sa.add(hooks3)
312 317 self.sa.add(hooks4)
313 318 self.sa.add(dotencode_disable)
314 319 self.sa.commit()
315 320 except:
316 321 self.sa.rollback()
317 322 raise
318 323
319 324
320 325 def create_ldap_options(self):
321 326 """Creates ldap settings"""
322 327
323 328 try:
324 329 for k in ['ldap_active', 'ldap_host', 'ldap_port', 'ldap_ldaps',
325 330 'ldap_dn_user', 'ldap_dn_pass', 'ldap_base_dn']:
326 331
327 332 setting = RhodeCodeSettings(k, '')
328 333 self.sa.add(setting)
329 334 self.sa.commit()
330 335 except:
331 336 self.sa.rollback()
332 337 raise
333 338
334 339 def config_prompt(self, test_repo_path=''):
335 340 log.info('Setting up repositories config')
336 341
337 342 if not self.tests and not test_repo_path:
338 343 path = raw_input('Specify valid full path to your repositories'
339 344 ' you can change this later in application settings:')
340 345 else:
341 346 path = test_repo_path
342 347
343 348 if not os.path.isdir(path):
344 349 log.error('You entered wrong path: %s', path)
345 350 sys.exit()
346 351
347 352 self.create_ui_settings()
348 353
349 354 #HG UI OPTIONS
350 355 web1 = RhodeCodeUi()
351 356 web1.ui_section = 'web'
352 357 web1.ui_key = 'push_ssl'
353 358 web1.ui_value = 'false'
354 359
355 360 web2 = RhodeCodeUi()
356 361 web2.ui_section = 'web'
357 362 web2.ui_key = 'allow_archive'
358 363 web2.ui_value = 'gz zip bz2'
359 364
360 365 web3 = RhodeCodeUi()
361 366 web3.ui_section = 'web'
362 367 web3.ui_key = 'allow_push'
363 368 web3.ui_value = '*'
364 369
365 370 web4 = RhodeCodeUi()
366 371 web4.ui_section = 'web'
367 372 web4.ui_key = 'baseurl'
368 373 web4.ui_value = '/'
369 374
370 375 paths = RhodeCodeUi()
371 376 paths.ui_section = 'paths'
372 377 paths.ui_key = '/'
373 378 paths.ui_value = path
374 379
375 380
376 381 hgsettings1 = RhodeCodeSettings('realm', 'RhodeCode authentication')
377 382 hgsettings2 = RhodeCodeSettings('title', 'RhodeCode')
378 383 hgsettings3 = RhodeCodeSettings('ga_code', '')
379 384
380 385
381 386 try:
382 387 self.sa.add(web1)
383 388 self.sa.add(web2)
384 389 self.sa.add(web3)
385 390 self.sa.add(web4)
386 391 self.sa.add(paths)
387 392 self.sa.add(hgsettings1)
388 393 self.sa.add(hgsettings2)
389 394 self.sa.add(hgsettings3)
390 395
391 396 self.sa.commit()
392 397 except:
393 398 self.sa.rollback()
394 399 raise
395 400
396 401 self.create_ldap_options()
397 402
398 403 log.info('created ui config')
399 404
400 405 def create_user(self, username, password, email='', admin=False):
401 406 log.info('creating administrator user %s', username)
402 407 new_user = User()
403 408 new_user.username = username
404 409 new_user.password = get_crypt_password(password)
405 410 new_user.name = 'RhodeCode'
406 411 new_user.lastname = 'Admin'
407 412 new_user.email = email
408 413 new_user.admin = admin
409 414 new_user.active = True
410 415
411 416 try:
412 417 self.sa.add(new_user)
413 418 self.sa.commit()
414 419 except:
415 420 self.sa.rollback()
416 421 raise
417 422
418 423 def create_default_user(self):
419 424 log.info('creating default user')
420 425 #create default user for handling default permissions.
421 426 def_user = User()
422 427 def_user.username = 'default'
423 428 def_user.password = get_crypt_password(str(uuid.uuid1())[:8])
424 429 def_user.name = 'Anonymous'
425 430 def_user.lastname = 'User'
426 431 def_user.email = 'anonymous@rhodecode.org'
427 432 def_user.admin = False
428 433 def_user.active = False
429 434 try:
430 435 self.sa.add(def_user)
431 436 self.sa.commit()
432 437 except:
433 438 self.sa.rollback()
434 439 raise
435 440
436 441 def create_permissions(self):
437 442 #module.(access|create|change|delete)_[name]
438 443 #module.(read|write|owner)
439 444 perms = [('repository.none', 'Repository no access'),
440 445 ('repository.read', 'Repository read access'),
441 446 ('repository.write', 'Repository write access'),
442 447 ('repository.admin', 'Repository admin access'),
443 448 ('hg.admin', 'Hg Administrator'),
444 449 ('hg.create.repository', 'Repository create'),
445 450 ('hg.create.none', 'Repository creation disabled'),
446 451 ('hg.register.none', 'Register disabled'),
447 452 ('hg.register.manual_activate', 'Register new user with rhodecode without manual activation'),
448 453 ('hg.register.auto_activate', 'Register new user with rhodecode without auto activation'),
449 454 ]
450 455
451 456 for p in perms:
452 457 new_perm = Permission()
453 458 new_perm.permission_name = p[0]
454 459 new_perm.permission_longname = p[1]
455 460 try:
456 461 self.sa.add(new_perm)
457 462 self.sa.commit()
458 463 except:
459 464 self.sa.rollback()
460 465 raise
461 466
462 467 def populate_default_permissions(self):
463 468 log.info('creating default user permissions')
464 469
465 470 default_user = self.sa.query(User)\
466 471 .filter(User.username == 'default').scalar()
467 472
468 473 reg_perm = UserToPerm()
469 474 reg_perm.user = default_user
470 475 reg_perm.permission = self.sa.query(Permission)\
471 476 .filter(Permission.permission_name == 'hg.register.manual_activate')\
472 477 .scalar()
473 478
474 479 create_repo_perm = UserToPerm()
475 480 create_repo_perm.user = default_user
476 481 create_repo_perm.permission = self.sa.query(Permission)\
477 482 .filter(Permission.permission_name == 'hg.create.repository')\
478 483 .scalar()
479 484
480 485 default_repo_perm = UserToPerm()
481 486 default_repo_perm.user = default_user
482 487 default_repo_perm.permission = self.sa.query(Permission)\
483 488 .filter(Permission.permission_name == 'repository.read')\
484 489 .scalar()
485 490
486 491 try:
487 492 self.sa.add(reg_perm)
488 493 self.sa.add(create_repo_perm)
489 494 self.sa.add(default_repo_perm)
490 495 self.sa.commit()
491 496 except:
492 497 self.sa.rollback()
493 498 raise
494 499
@@ -1,127 +1,88 b''
1 1 import logging
2 2 import datetime
3 3
4 4 from sqlalchemy import *
5 5 from sqlalchemy.exc import DatabaseError
6 6 from sqlalchemy.orm import relation, backref, class_mapper
7 7 from sqlalchemy.orm.session import Session
8 8 from rhodecode.model.meta import Base
9 9 from rhodecode.model.db import BaseModel
10 10
11 11 from rhodecode.lib.dbmigrate.migrate import *
12 from rhodecode.lib.dbmigrate.migrate.changeset import *
12 13
13 14 log = logging.getLogger(__name__)
14 15
15 16 def upgrade(migrate_engine):
16 17 """ Upgrade operations go here.
17 18 Don't create your own engine; bind migrate_engine to your metadata
18 19 """
19 20
20 21 #==========================================================================
21 22 # Upgrade of `users` table
22 23 #==========================================================================
23 24 tblname = 'users'
24 25 tbl = Table(tblname, MetaData(bind=migrate_engine), autoload=True,
25 26 autoload_with=migrate_engine)
26 27
27 28 #ADD is_ldap column
28 29 is_ldap = Column("is_ldap", Boolean(), nullable=True,
29 30 unique=None, default=False)
30 31 is_ldap.create(tbl, populate_default=True)
31 32 is_ldap.alter(nullable=False)
32 33
33 34 #==========================================================================
34 35 # Upgrade of `user_logs` table
35 36 #==========================================================================
36 37
37 38 tblname = 'users'
38 39 tbl = Table(tblname, MetaData(bind=migrate_engine), autoload=True,
39 40 autoload_with=migrate_engine)
40 41
41 42 #ADD revision column
42 43 revision = Column('revision', TEXT(length=None, convert_unicode=False,
43 44 assert_unicode=None),
44 45 nullable=True, unique=None, default=None)
45 46 revision.create(tbl)
46 47
47 48
48 49
49 50 #==========================================================================
50 51 # Upgrade of `repositories` table
51 52 #==========================================================================
52 53 tblname = 'repositories'
53 54 tbl = Table(tblname, MetaData(bind=migrate_engine), autoload=True,
54 55 autoload_with=migrate_engine)
55 56
56 57 #ADD repo_type column#
57 58 repo_type = Column("repo_type", String(length=None, convert_unicode=False,
58 59 assert_unicode=None),
59 60 nullable=True, unique=False, default='hg')
60 61
61 62 repo_type.create(tbl, populate_default=True)
62 63 #repo_type.alter(nullable=False)
63 64
64 65 #ADD statistics column#
65 66 enable_statistics = Column("statistics", Boolean(), nullable=True,
66 67 unique=None, default=True)
67 68 enable_statistics.create(tbl)
68 69
69 70 #==========================================================================
70 71 # Add table `user_followings`
71 72 #==========================================================================
72 tblname = 'user_followings'
73
74 class UserFollowing(Base, BaseModel):
75 __tablename__ = 'user_followings'
76 __table_args__ = (UniqueConstraint('user_id', 'follows_repository_id'),
77 UniqueConstraint('user_id', 'follows_user_id')
78 , {'useexisting':True})
79
80 user_following_id = Column("user_following_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
81 user_id = Column("user_id", Integer(), ForeignKey(u'users.user_id'), nullable=False, unique=None, default=None)
82 follows_repo_id = Column("follows_repository_id", Integer(), ForeignKey(u'repositories.repo_id'), nullable=True, unique=None, default=None)
83 follows_user_id = Column("follows_user_id", Integer(), ForeignKey(u'users.user_id'), nullable=True, unique=None, default=None)
84
85 user = relation('User', primaryjoin='User.user_id==UserFollowing.user_id')
86
87 follows_user = relation('User', primaryjoin='User.user_id==UserFollowing.follows_user_id')
88 follows_repository = relation('Repository')
89
90 Base.metadata.tables[tblname].create(migrate_engine)
73 from rhodecode.model.db import UserFollowing
74 UserFollowing().__table__.create()
91 75
92 76 #==========================================================================
93 77 # Add table `cache_invalidation`
94 78 #==========================================================================
95 tblname = 'cache_invalidation'
96
97 class CacheInvalidation(Base, BaseModel):
98 __tablename__ = 'cache_invalidation'
99 __table_args__ = (UniqueConstraint('cache_key'), {'useexisting':True})
100 cache_id = Column("cache_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
101 cache_key = Column("cache_key", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
102 cache_args = Column("cache_args", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
103 cache_active = Column("cache_active", Boolean(), nullable=True, unique=None, default=False)
104
105
106 def __init__(self, cache_key, cache_args=''):
107 self.cache_key = cache_key
108 self.cache_args = cache_args
109 self.cache_active = False
110
111 def __repr__(self):
112 return "<CacheInvalidation('%s:%s')>" % (self.cache_id, self.cache_key)
113
114 Base.metadata.tables[tblname].create(migrate_engine)
79 from rhodecode.model.db import CacheInvalidation
80 CacheInvalidation().__table__.create()
115 81
116 82 return
117 83
118
119
120
121
122
123 84 def downgrade(migrate_engine):
124 85 meta = MetaData()
125 86 meta.bind = migrate_engine
126 87
127 88
@@ -1,87 +1,59 b''
1 1 import logging
2 2 import datetime
3 3
4 4 from sqlalchemy import *
5 5 from sqlalchemy.exc import DatabaseError
6 6 from sqlalchemy.orm import relation, backref, class_mapper
7 7 from sqlalchemy.orm.session import Session
8
9
10 from rhodecode.lib.dbmigrate.migrate import *
11 from rhodecode.lib.dbmigrate.migrate.changeset import *
12
8 13 from rhodecode.model.meta import Base
9 14 from rhodecode.model.db import BaseModel
10 15
11 from rhodecode.lib.dbmigrate.migrate import *
12
13 16 log = logging.getLogger(__name__)
14 17
15 18 def upgrade(migrate_engine):
16 19 """ Upgrade operations go here.
17 20 Don't create your own engine; bind migrate_engine to your metadata
18 21 """
19 22
20 23 #==========================================================================
21 24 # Add table `groups``
22 25 #==========================================================================
23 tblname = 'groups'
24
25 class Group(Base, BaseModel):
26 __tablename__ = 'groups'
27 __table_args__ = (UniqueConstraint('group_name'), {'useexisting':True},)
28
29 group_id = Column("group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
30 group_name = Column("group_name", String(length=None, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None)
31 group_parent_id = Column("group_parent_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=None, default=None)
32
33 parent_group = relation('Group', remote_side=group_id)
34
35
36 def __init__(self, group_name='', parent_group=None):
37 self.group_name = group_name
38 self.parent_group = parent_group
39
40 def __repr__(self):
41 return "<%s('%s:%s')>" % (self.__class__.__name__, self.group_id,
42 self.group_name)
43
44 Base.metadata.tables[tblname].create(migrate_engine)
26 from rhodecode.model.db import Group
27 Group().__table__.create()
45 28
46 29 #==========================================================================
47 30 # Add table `group_to_perm`
48 31 #==========================================================================
49 tblname = 'group_to_perm'
50
51 class GroupToPerm(Base, BaseModel):
52 __tablename__ = 'group_to_perm'
53 __table_args__ = (UniqueConstraint('group_id', 'permission_id'), {'useexisting':True})
54
55 group_to_perm_id = Column("group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
56 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
57 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
58 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
59
60 user = relation('User')
61 permission = relation('Permission')
62 group = relation('Group')
63
64 Base.metadata.tables[tblname].create(migrate_engine)
32 from rhodecode.model.db import GroupToPerm
33 GroupToPerm().__table__.create()
65 34
66 35 #==========================================================================
67 36 # Upgrade of `repositories` table
68 37 #==========================================================================
69 38 tblname = 'repositories'
70 39 tbl = Table(tblname, MetaData(bind=migrate_engine), autoload=True,
71 40 autoload_with=migrate_engine)
72 41
73 42 #ADD group_id column#
74 group_id = Column("group_id", Integer(), ForeignKey(u'groups.group_id'),
43 group_id = Column("group_id", Integer(), #ForeignKey('groups.group_id'),
75 44 nullable=True, unique=False, default=None)
76 45
77 group_id.create(tbl, populate_default=True)
46 group_id.create(tbl)
78 47
79
48 # TODO: fix this somehow ?!
49 # cons = ForeignKeyConstraint([tbl.c.group_id], ['groups.group_id'], table=tbl)
50 #
51 # cons.create()
80 52 return
81 53
82 54
83 55 def downgrade(migrate_engine):
84 56 meta = MetaData()
85 57 meta.bind = migrate_engine
86 58
87 59
@@ -1,298 +1,298 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 rhodecode.model.db
4 4 ~~~~~~~~~~~~~~~~~~
5 5
6 6 Database Models for RhodeCode
7 7
8 8 :created_on: Apr 08, 2010
9 9 :author: marcink
10 10 :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
11 11 :license: GPLv3, see COPYING for more details.
12 12 """
13 13 # This program is free software; you can redistribute it and/or
14 14 # modify it under the terms of the GNU General Public License
15 15 # as published by the Free Software Foundation; version 2
16 16 # of the License or (at your opinion) any later version of the license.
17 17 #
18 18 # This program is distributed in the hope that it will be useful,
19 19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 21 # GNU General Public License for more details.
22 22 #
23 23 # You should have received a copy of the GNU General Public License
24 24 # along with this program; if not, write to the Free Software
25 25 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
26 26 # MA 02110-1301, USA.
27 27 import logging
28 28 import datetime
29 29
30 30 from sqlalchemy import *
31 31 from sqlalchemy.exc import DatabaseError
32 32 from sqlalchemy.orm import relation, backref, class_mapper
33 33 from sqlalchemy.orm.session import Session
34 34
35 35 from rhodecode.model.meta import Base
36 36
37 37 log = logging.getLogger(__name__)
38 38
39 39 class BaseModel(object):
40 40
41 41 @classmethod
42 42 def _get_keys(cls):
43 43 """return column names for this model """
44 44 return class_mapper(cls).c.keys()
45 45
46 46 def get_dict(self):
47 47 """return dict with keys and values corresponding
48 48 to this model data """
49 49
50 50 d = {}
51 51 for k in self._get_keys():
52 52 d[k] = getattr(self, k)
53 53 return d
54 54
55 55 def get_appstruct(self):
56 56 """return list with keys and values tupples corresponding
57 57 to this model data """
58 58
59 59 l = []
60 60 for k in self._get_keys():
61 61 l.append((k, getattr(self, k),))
62 62 return l
63 63
64 64 def populate_obj(self, populate_dict):
65 65 """populate model with data from given populate_dict"""
66 66
67 67 for k in self._get_keys():
68 68 if k in populate_dict:
69 69 setattr(self, k, populate_dict[k])
70 70
71 71 class RhodeCodeSettings(Base, BaseModel):
72 72 __tablename__ = 'rhodecode_settings'
73 73 __table_args__ = (UniqueConstraint('app_settings_name'), {'useexisting':True})
74 74 app_settings_id = Column("app_settings_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
75 75 app_settings_name = Column("app_settings_name", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
76 76 app_settings_value = Column("app_settings_value", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
77 77
78 def __init__(self, k, v):
78 def __init__(self, k='', v=''):
79 79 self.app_settings_name = k
80 80 self.app_settings_value = v
81 81
82 82 def __repr__(self):
83 83 return "<%s('%s:%s')>" % (self.__class__.__name__,
84 84 self.app_settings_name, self.app_settings_value)
85 85
86 86 class RhodeCodeUi(Base, BaseModel):
87 87 __tablename__ = 'rhodecode_ui'
88 88 __table_args__ = {'useexisting':True}
89 89 ui_id = Column("ui_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
90 90 ui_section = Column("ui_section", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
91 91 ui_key = Column("ui_key", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
92 92 ui_value = Column("ui_value", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
93 93 ui_active = Column("ui_active", Boolean(), nullable=True, unique=None, default=True)
94 94
95 95
96 96 class User(Base, BaseModel):
97 97 __tablename__ = 'users'
98 98 __table_args__ = (UniqueConstraint('username'), UniqueConstraint('email'), {'useexisting':True})
99 99 user_id = Column("user_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
100 100 username = Column("username", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
101 101 password = Column("password", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
102 102 active = Column("active", Boolean(), nullable=True, unique=None, default=None)
103 103 admin = Column("admin", Boolean(), nullable=True, unique=None, default=False)
104 104 name = Column("name", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
105 105 lastname = Column("lastname", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
106 106 email = Column("email", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
107 107 last_login = Column("last_login", DateTime(timezone=False), nullable=True, unique=None, default=None)
108 108 is_ldap = Column("is_ldap", Boolean(), nullable=False, unique=None, default=False)
109 109
110 110 user_log = relation('UserLog', cascade='all')
111 111 user_perms = relation('UserToPerm', primaryjoin="User.user_id==UserToPerm.user_id", cascade='all')
112 112
113 113 repositories = relation('Repository')
114 114 user_followers = relation('UserFollowing', primaryjoin='UserFollowing.follows_user_id==User.user_id', cascade='all')
115 115
116 116 @property
117 117 def full_contact(self):
118 118 return '%s %s <%s>' % (self.name, self.lastname, self.email)
119 119
120 120
121 121 @property
122 122 def is_admin(self):
123 123 return self.admin
124 124
125 125 def __repr__(self):
126 126 return "<%s('id:%s:%s')>" % (self.__class__.__name__,
127 127 self.user_id, self.username)
128 128
129 129 def update_lastlogin(self):
130 130 """Update user lastlogin"""
131 131
132 132 try:
133 133 session = Session.object_session(self)
134 134 self.last_login = datetime.datetime.now()
135 135 session.add(self)
136 136 session.commit()
137 137 log.debug('updated user %s lastlogin', self.username)
138 138 except (DatabaseError,):
139 139 session.rollback()
140 140
141 141
142 142 class UserLog(Base, BaseModel):
143 143 __tablename__ = 'user_logs'
144 144 __table_args__ = {'useexisting':True}
145 145 user_log_id = Column("user_log_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
146 146 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
147 147 repository_id = Column("repository_id", Integer(length=None, convert_unicode=False, assert_unicode=None), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
148 148 repository_name = Column("repository_name", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
149 149 user_ip = Column("user_ip", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
150 150 action = Column("action", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
151 151 action_date = Column("action_date", DateTime(timezone=False), nullable=True, unique=None, default=None)
152 152
153 153 user = relation('User')
154 154 repository = relation('Repository')
155 155
156 156 class Repository(Base, BaseModel):
157 157 __tablename__ = 'repositories'
158 158 __table_args__ = (UniqueConstraint('repo_name'), {'useexisting':True},)
159 159 repo_id = Column("repo_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
160 160 repo_name = Column("repo_name", String(length=None, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None)
161 161 repo_type = Column("repo_type", String(length=None, convert_unicode=False, assert_unicode=None), nullable=False, unique=False, default='hg')
162 162 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
163 163 private = Column("private", Boolean(), nullable=True, unique=None, default=None)
164 164 enable_statistics = Column("statistics", Boolean(), nullable=True, unique=None, default=True)
165 165 description = Column("description", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
166 166 fork_id = Column("fork_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=False, default=None)
167 167 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=False, default=None)
168 168
169 169 user = relation('User')
170 170 fork = relation('Repository', remote_side=repo_id)
171 171 group = relation('Group')
172 172 repo_to_perm = relation('RepoToPerm', cascade='all')
173 173 stats = relation('Statistics', cascade='all', uselist=False)
174 174
175 175 repo_followers = relation('UserFollowing', primaryjoin='UserFollowing.follows_repo_id==Repository.repo_id', cascade='all')
176 176
177 177 def __repr__(self):
178 178 return "<%s('%s:%s')>" % (self.__class__.__name__,
179 179 self.repo_id, self.repo_name)
180 180
181 181 class Group(Base, BaseModel):
182 182 __tablename__ = 'groups'
183 183 __table_args__ = (UniqueConstraint('group_name'), {'useexisting':True},)
184 184
185 185 group_id = Column("group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
186 186 group_name = Column("group_name", String(length=None, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None)
187 187 group_parent_id = Column("group_parent_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=None, default=None)
188 188
189 189 parent_group = relation('Group', remote_side=group_id)
190 190
191 191
192 192 def __init__(self, group_name='', parent_group=None):
193 193 self.group_name = group_name
194 194 self.parent_group = parent_group
195 195
196 196 def __repr__(self):
197 197 return "<%s('%s:%s')>" % (self.__class__.__name__, self.group_id,
198 198 self.group_name)
199 199
200 200 class Permission(Base, BaseModel):
201 201 __tablename__ = 'permissions'
202 202 __table_args__ = {'useexisting':True}
203 203 permission_id = Column("permission_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
204 204 permission_name = Column("permission_name", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
205 205 permission_longname = Column("permission_longname", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
206 206
207 207 def __repr__(self):
208 208 return "<%s('%s:%s')>" % (self.__class__.__name__,
209 209 self.permission_id, self.permission_name)
210 210
211 211 class RepoToPerm(Base, BaseModel):
212 212 __tablename__ = 'repo_to_perm'
213 213 __table_args__ = (UniqueConstraint('user_id', 'repository_id'), {'useexisting':True})
214 214 repo_to_perm_id = Column("repo_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
215 215 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
216 216 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
217 217 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
218 218
219 219 user = relation('User')
220 220 permission = relation('Permission')
221 221 repository = relation('Repository')
222 222
223 223 class UserToPerm(Base, BaseModel):
224 224 __tablename__ = 'user_to_perm'
225 225 __table_args__ = (UniqueConstraint('user_id', 'permission_id'), {'useexisting':True})
226 226 user_to_perm_id = Column("user_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
227 227 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
228 228 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
229 229
230 230 user = relation('User')
231 231 permission = relation('Permission')
232 232
233 233 class GroupToPerm(Base, BaseModel):
234 234 __tablename__ = 'group_to_perm'
235 235 __table_args__ = (UniqueConstraint('group_id', 'permission_id'), {'useexisting':True})
236 236
237 237 group_to_perm_id = Column("group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
238 238 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
239 239 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
240 240 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
241 241
242 242 user = relation('User')
243 243 permission = relation('Permission')
244 244 group = relation('Group')
245 245
246 246 class Statistics(Base, BaseModel):
247 247 __tablename__ = 'statistics'
248 248 __table_args__ = (UniqueConstraint('repository_id'), {'useexisting':True})
249 249 stat_id = Column("stat_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
250 250 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=True, default=None)
251 251 stat_on_revision = Column("stat_on_revision", Integer(), nullable=False)
252 252 commit_activity = Column("commit_activity", LargeBinary(), nullable=False)#JSON data
253 253 commit_activity_combined = Column("commit_activity_combined", LargeBinary(), nullable=False)#JSON data
254 254 languages = Column("languages", LargeBinary(), nullable=False)#JSON data
255 255
256 256 repository = relation('Repository', single_parent=True)
257 257
258 258 class UserFollowing(Base, BaseModel):
259 259 __tablename__ = 'user_followings'
260 260 __table_args__ = (UniqueConstraint('user_id', 'follows_repository_id'),
261 261 UniqueConstraint('user_id', 'follows_user_id')
262 262 , {'useexisting':True})
263 263
264 264 user_following_id = Column("user_following_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
265 265 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
266 266 follows_repo_id = Column("follows_repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=None, default=None)
267 267 follows_user_id = Column("follows_user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
268 268
269 269 user = relation('User', primaryjoin='User.user_id==UserFollowing.user_id')
270 270
271 271 follows_user = relation('User', primaryjoin='User.user_id==UserFollowing.follows_user_id')
272 272 follows_repository = relation('Repository')
273 273
274 274 class CacheInvalidation(Base, BaseModel):
275 275 __tablename__ = 'cache_invalidation'
276 276 __table_args__ = (UniqueConstraint('cache_key'), {'useexisting':True})
277 277 cache_id = Column("cache_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
278 278 cache_key = Column("cache_key", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
279 279 cache_args = Column("cache_args", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
280 280 cache_active = Column("cache_active", Boolean(), nullable=True, unique=None, default=False)
281 281
282 282
283 283 def __init__(self, cache_key, cache_args=''):
284 284 self.cache_key = cache_key
285 285 self.cache_args = cache_args
286 286 self.cache_active = False
287 287
288 288 def __repr__(self):
289 289 return "<%s('%s:%s')>" % (self.__class__.__name__,
290 290 self.cache_id, self.cache_key)
291 291
292 292 class DbMigrateVersion(Base, BaseModel):
293 293 __tablename__ = 'db_migrate_version'
294 294 __table_args__ = {'useexisting':True}
295 295 repository_id = Column('repository_id', String(250), primary_key=True)
296 296 repository_path = Column('repository_path', Text)
297 297 version = Column('version', Integer)
298 298
General Comments 0
You need to be logged in to leave comments. Login now