diff --git a/rhodecode/model/db.py b/rhodecode/model/db.py
--- a/rhodecode/model/db.py
+++ b/rhodecode/model/db.py
@@ -24,12 +24,12 @@
# along with this program. If not, see .
import os
+import time
import logging
import datetime
import traceback
import hashlib
-import time
-from collections import defaultdict
+import collections
from sqlalchemy import *
from sqlalchemy.ext.hybrid import hybrid_property
@@ -131,6 +131,11 @@ class BaseModel(object):
@classmethod
def getAll(cls):
+ # deprecated and left for backward compatibility
+ return cls.get_all()
+
+ @classmethod
+ def get_all(cls):
return cls.query().all()
@classmethod
@@ -265,6 +270,11 @@ class RhodeCodeUi(Base, BaseModel):
ui_value = Column("ui_value", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
ui_active = Column("ui_active", Boolean(), nullable=True, unique=None, default=True)
+ # def __init__(self, section='', key='', value=''):
+ # self.ui_section = section
+ # self.ui_key = key
+ # self.ui_value = value
+
@classmethod
def get_by_key(cls, key):
return cls.query().filter(cls.ui_key == key).scalar()
@@ -315,10 +325,7 @@ class User(Base, BaseModel):
'mysql_charset': 'utf8'}
)
DEFAULT_USER = 'default'
- DEFAULT_PERMISSIONS = [
- 'hg.register.manual_activate', 'hg.create.repository',
- 'hg.fork.repository', 'repository.read', 'group.read'
- ]
+
user_id = Column("user_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
username = Column("username", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
password = Column("password", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
@@ -490,6 +497,20 @@ class User(Base, BaseModel):
Session().add(self)
log.debug('updated user %s lastlogin' % self.username)
+ @classmethod
+ def get_first_admin(cls):
+ user = User.query().filter(User.admin == True).first()
+ if user is None:
+ raise Exception('Missing administrative account!')
+ return user
+
+ @classmethod
+ def get_default_user(cls, cache=False):
+ user = User.get_by_username(User.DEFAULT_USER, cache=cache)
+ if user is None:
+ raise Exception('Missing default account!')
+ return user
+
def get_api_data(self):
"""
Common function for generating user related data for API
@@ -597,6 +618,11 @@ class UserLog(Base, BaseModel):
action = Column("action", UnicodeText(1200000, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
action_date = Column("action_date", DateTime(timezone=False), nullable=True, unique=None, default=None)
+ def __unicode__(self):
+ return u"<%s('id:%s:%s')>" % (self.__class__.__name__,
+ self.repository_name,
+ self.action)
+
@property
def action_as_day(self):
return datetime.date(*self.action_date.timetuple()[:3])
@@ -616,13 +642,21 @@ class UserGroup(Base, BaseModel):
users_group_name = Column("users_group_name", String(255, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None)
users_group_active = Column("users_group_active", Boolean(), nullable=True, unique=None, default=None)
inherit_default_permissions = Column("users_group_inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
+ user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
members = relationship('UserGroupMember', cascade="all, delete, delete-orphan", lazy="joined")
users_group_to_perm = relationship('UserGroupToPerm', cascade='all')
users_group_repo_to_perm = relationship('UserGroupRepoToPerm', cascade='all')
+ users_group_repo_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all')
+ user_user_group_to_perm = relationship('UserUserGroupToPerm ', cascade='all')
+ user_group_user_group_to_perm = relationship('UserGroupUserGroupToPerm ', primaryjoin="UserGroupUserGroupToPerm.target_user_group_id==UserGroup.users_group_id", cascade='all')
+
+ user = relationship('User')
def __unicode__(self):
- return u'' % (self.users_group_name)
+ return u"<%s('id:%s:%s')>" % (self.__class__.__name__,
+ self.users_group_id,
+ self.users_group_name)
@classmethod
def get_by_group_name(cls, group_name, cache=False,
@@ -983,8 +1017,10 @@ class Repository(Base, BaseModel):
return data
@classmethod
- def lock(cls, repo, user_id):
- repo.locked = [user_id, time.time()]
+ def lock(cls, repo, user_id, lock_time=None):
+ if not lock_time:
+ lock_time = time.time()
+ repo.locked = [user_id, lock_time]
Session().add(repo)
Session().commit()
@@ -1094,7 +1130,7 @@ class Repository(Base, BaseModel):
.filter(ChangesetComment.repo == self)
if revisions:
cmts = cmts.filter(ChangesetComment.revision.in_(revisions))
- grouped = defaultdict(list)
+ grouped = collections.defaultdict(list)
for cmt in cmts.all():
grouped[cmt.revision].append(cmt)
return grouped
@@ -1104,7 +1140,6 @@ class Repository(Base, BaseModel):
Returns statuses for this repository
:param revisions: list of revisions to get statuses for
- :type revisions: list
"""
statuses = ChangesetStatus.query()\
@@ -1141,20 +1176,16 @@ class Repository(Base, BaseModel):
# SCM CACHE INSTANCE
#==========================================================================
- @property
- def invalidate(self):
- return CacheInvalidation.invalidate(self.repo_name)
-
def set_invalidate(self):
"""
- set a cache for invalidation for this instance
+ Mark caches of this repo as invalid.
"""
- CacheInvalidation.set_invalidate(repo_name=self.repo_name)
+ CacheInvalidation.set_invalidate(self.repo_name)
def scm_instance_no_cache(self):
return self.__get_instance()
- @LazyProperty
+ @property
def scm_instance(self):
import rhodecode
full_cache = str2bool(rhodecode.CONFIG.get('vcs_full_cache'))
@@ -1162,27 +1193,18 @@ class Repository(Base, BaseModel):
return self.scm_instance_cached()
return self.__get_instance()
- def scm_instance_cached(self, cache_map=None):
+ def scm_instance_cached(self, valid_cache_keys=None):
@cache_region('long_term')
def _c(repo_name):
return self.__get_instance()
rn = self.repo_name
- log.debug('Getting cached instance of repo')
- if cache_map:
- # get using prefilled cache_map
- invalidate_repo = cache_map[self.repo_name]
- if invalidate_repo:
- invalidate_repo = (None if invalidate_repo.cache_active
- else invalidate_repo)
+ valid = CacheInvalidation.test_and_set_valid(rn, None, valid_cache_keys=valid_cache_keys)
+ if not valid:
+ log.debug('Cache for %s invalidated, getting new object' % (rn))
+ region_invalidate(_c, None, rn)
else:
- # get from invalidate
- invalidate_repo = self.invalidate
-
- if invalidate_repo is not None:
- region_invalidate(_c, None, rn)
- # update our cache
- CacheInvalidation.set_valid(invalidate_repo.cache_key)
+ log.debug('Getting obj for %s from cache' % (rn))
return _c(rn)
def __get_instance(self):
@@ -1227,19 +1249,20 @@ class RepoGroup(Base, BaseModel):
group_parent_id = Column("group_parent_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=None, default=None)
group_description = Column("group_description", String(10000, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
+ user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
repo_group_to_perm = relationship('UserRepoGroupToPerm', cascade='all', order_by='UserRepoGroupToPerm.group_to_perm_id')
users_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all')
-
parent_group = relationship('RepoGroup', remote_side=group_id)
+ user = relationship('User')
def __init__(self, group_name='', parent_group=None):
self.group_name = group_name
self.parent_group = parent_group
def __unicode__(self):
- return u"<%s('%s:%s')>" % (self.__class__.__name__, self.group_id,
- self.group_name)
+ return u"<%s('id:%s:%s')>" % (self.__class__.__name__, self.group_id,
+ self.group_name)
@classmethod
def groups_choices(cls, groups=None, show_empty_group=True):
@@ -1249,7 +1272,7 @@ class RepoGroup(Base, BaseModel):
repo_groups = []
if show_empty_group:
- repo_groups = [('-1', '-- %s --' % _('top level'))]
+ repo_groups = [('-1', u'-- %s --' % _('top level'))]
sep = ' » '
_name = lambda k: _literal(sep.join(k))
@@ -1385,6 +1408,8 @@ class Permission(Base, BaseModel):
'mysql_charset': 'utf8'},
)
PERMS = [
+ ('hg.admin', _('RhodeCode Administrator')),
+
('repository.none', _('Repository no access')),
('repository.read', _('Repository read access')),
('repository.write', _('Repository write access')),
@@ -1395,20 +1420,46 @@ class Permission(Base, BaseModel):
('group.write', _('Repository group write access')),
('group.admin', _('Repository group admin access')),
- ('hg.admin', _('RhodeCode Administrator')),
+ ('usergroup.none', _('User group no access')),
+ ('usergroup.read', _('User group read access')),
+ ('usergroup.write', _('User group write access')),
+ ('usergroup.admin', _('User group admin access')),
+
+ ('hg.repogroup.create.false', _('Repository Group creation disabled')),
+ ('hg.repogroup.create.true', _('Repository Group creation enabled')),
+
+ ('hg.usergroup.create.false', _('User Group creation disabled')),
+ ('hg.usergroup.create.true', _('User Group creation enabled')),
+
('hg.create.none', _('Repository creation disabled')),
('hg.create.repository', _('Repository creation enabled')),
+
('hg.fork.none', _('Repository forking disabled')),
('hg.fork.repository', _('Repository forking enabled')),
- ('hg.register.none', _('Register disabled')),
- ('hg.register.manual_activate', _('Register new user with RhodeCode '
- 'with manual activation')),
+
+ ('hg.register.none', _('Registration disabled')),
+ ('hg.register.manual_activate', _('User Registration with manual account activation')),
+ ('hg.register.auto_activate', _('User Registration with automatic account activation')),
+
+ ('hg.extern_activate.manual', _('Manual activation of external account')),
+ ('hg.extern_activate.auto', _('Automatic activation of external account')),
+
+ ]
- ('hg.register.auto_activate', _('Register new user with RhodeCode '
- 'with auto activation')),
+ #definition of system default permissions for DEFAULT user
+ DEFAULT_USER_PERMISSIONS = [
+ 'repository.read',
+ 'group.read',
+ 'usergroup.read',
+ 'hg.create.repository',
+ 'hg.fork.repository',
+ 'hg.register.manual_activate',
+ 'hg.extern_activate.auto',
]
# defines which permissions are more important higher the more important
+ # Weight defines which permissions are more important.
+ # The higher number the more important.
PERM_WEIGHTS = {
'repository.none': 0,
'repository.read': 1,
@@ -1420,10 +1471,20 @@ class Permission(Base, BaseModel):
'group.write': 3,
'group.admin': 4,
+ 'usergroup.none': 0,
+ 'usergroup.read': 1,
+ 'usergroup.write': 3,
+ 'usergroup.admin': 4,
+ 'hg.repogroup.create.false': 0,
+ 'hg.repogroup.create.true': 1,
+
+ 'hg.usergroup.create.false': 0,
+ 'hg.usergroup.create.true': 1,
+
'hg.fork.none': 0,
'hg.fork.repository': 1,
'hg.create.none': 0,
- 'hg.create.repository':1
+ 'hg.create.repository': 1
}
permission_id = Column("permission_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
@@ -1457,6 +1518,15 @@ class Permission(Base, BaseModel):
return q.all()
+ @classmethod
+ def get_default_user_group_perms(cls, default_user_id):
+ q = Session().query(UserUserGroupToPerm, UserGroup, cls)\
+ .join((UserGroup, UserUserGroupToPerm.user_group_id == UserGroup.users_group_id))\
+ .join((cls, UserUserGroupToPerm.permission_id == cls.permission_id))\
+ .filter(UserUserGroupToPerm.user_id == default_user_id)
+
+ return q.all()
+
class UserRepoToPerm(Base, BaseModel):
__tablename__ = 'repo_to_perm'
@@ -1484,7 +1554,36 @@ class UserRepoToPerm(Base, BaseModel):
return n
def __unicode__(self):
- return u' %s >' % (self.user, self.repository)
+ return u'<%s => %s >' % (self.user, self.repository)
+
+
+class UserUserGroupToPerm(Base, BaseModel):
+ __tablename__ = 'user_user_group_to_perm'
+ __table_args__ = (
+ UniqueConstraint('user_id', 'user_group_id', 'permission_id'),
+ {'extend_existing': True, 'mysql_engine': 'InnoDB',
+ 'mysql_charset': 'utf8'}
+ )
+ user_user_group_to_perm_id = Column("user_user_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
+ user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
+ permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
+ user_group_id = Column("user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
+
+ user = relationship('User')
+ user_group = relationship('UserGroup')
+ permission = relationship('Permission')
+
+ @classmethod
+ def create(cls, user, user_group, permission):
+ n = cls()
+ n.user = user
+ n.user_group = user_group
+ n.permission = permission
+ Session().add(n)
+ return n
+
+ def __unicode__(self):
+ return u'<%s => %s >' % (self.user, self.user_group)
class UserToPerm(Base, BaseModel):
@@ -1501,6 +1600,9 @@ class UserToPerm(Base, BaseModel):
user = relationship('User')
permission = relationship('Permission', lazy='joined')
+ def __unicode__(self):
+ return u'<%s => %s >' % (self.user, self.permission)
+
class UserGroupRepoToPerm(Base, BaseModel):
__tablename__ = 'users_group_repo_to_perm'
@@ -1528,7 +1630,37 @@ class UserGroupRepoToPerm(Base, BaseMode
return n
def __unicode__(self):
- return u' %s >' % (self.users_group, self.repository)
+ return u' %s >' % (self.users_group, self.repository)
+
+
+class UserGroupUserGroupToPerm(Base, BaseModel):
+ __tablename__ = 'user_group_user_group_to_perm'
+ __table_args__ = (
+ UniqueConstraint('target_user_group_id', 'user_group_id', 'permission_id'),
+ CheckConstraint('target_user_group_id != user_group_id'),
+ {'extend_existing': True, 'mysql_engine': 'InnoDB',
+ 'mysql_charset': 'utf8'}
+ )
+ user_group_user_group_to_perm_id = Column("user_group_user_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
+ target_user_group_id = Column("target_user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
+ permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
+ user_group_id = Column("user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
+
+ target_user_group = relationship('UserGroup', primaryjoin='UserGroupUserGroupToPerm.target_user_group_id==UserGroup.users_group_id')
+ user_group = relationship('UserGroup', primaryjoin='UserGroupUserGroupToPerm.user_group_id==UserGroup.users_group_id')
+ permission = relationship('Permission')
+
+ @classmethod
+ def create(cls, target_user_group, user_group, permission):
+ n = cls()
+ n.target_user_group = target_user_group
+ n.user_group = user_group
+ n.permission = permission
+ Session().add(n)
+ return n
+
+ def __unicode__(self):
+ return u' %s >' % (self.target_user_group, self.user_group)
class UserGroupToPerm(Base, BaseModel):
@@ -1636,146 +1768,115 @@ class CacheInvalidation(Base, BaseModel)
cache_id = Column("cache_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
# cache_key as created by _get_cache_key
cache_key = Column("cache_key", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
- # cache_args is usually a repo_name, possibly with _README/_RSS/_ATOM suffix
+ # cache_args is a repo_name
cache_args = Column("cache_args", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
- # instance sets cache_active True when it is caching, other instances set cache_active to False to invalidate
+ # instance sets cache_active True when it is caching,
+ # other instances set cache_active to False to indicate that this cache is invalid
cache_active = Column("cache_active", Boolean(), nullable=True, unique=None, default=False)
- def __init__(self, cache_key, cache_args=''):
+ def __init__(self, cache_key, repo_name=''):
self.cache_key = cache_key
- self.cache_args = cache_args
+ self.cache_args = repo_name
self.cache_active = False
def __unicode__(self):
- return u"<%s('%s:%s')>" % (self.__class__.__name__,
- self.cache_id, self.cache_key)
+ return u"<%s('%s:%s[%s]')>" % (self.__class__.__name__,
+ self.cache_id, self.cache_key, self.cache_active)
+
+ def _cache_key_partition(self):
+ prefix, repo_name, suffix = self.cache_key.partition(self.cache_args)
+ return prefix, repo_name, suffix
def get_prefix(self):
"""
- Guess prefix that might have been used in _get_cache_key to generate self.cache_key .
- Only used for informational purposes in repo_edit.html .
+ get prefix that might have been used in _get_cache_key to
+ generate self.cache_key. Only used for informational purposes
+ in repo_edit.html.
+ """
+ # prefix, repo_name, suffix
+ return self._cache_key_partition()[0]
+
+ def get_suffix(self):
"""
- _split = self.cache_key.split(self.cache_args, 1)
- if len(_split) == 2:
- return _split[0]
- return ''
+ get suffix that might have been used in _get_cache_key to
+ generate self.cache_key. Only used for informational purposes
+ in repo_edit.html.
+ """
+ # prefix, repo_name, suffix
+ return self._cache_key_partition()[2]
+
+ @classmethod
+ def clear_cache(cls):
+ """
+ Delete all cache keys from database.
+ Should only be run when all instances are down and all entries thus stale.
+ """
+ cls.query().delete()
+ Session().commit()
@classmethod
def _get_cache_key(cls, key):
"""
Wrapper for generating a unique cache key for this instance and "key".
+ key must / will start with a repo_name which will be stored in .cache_args .
"""
import rhodecode
prefix = rhodecode.CONFIG.get('instance_id', '')
return "%s%s" % (prefix, key)
@classmethod
- def _get_or_create_inv_obj(cls, key, repo_name, commit=True):
- inv_obj = Session().query(cls).filter(cls.cache_key == key).scalar()
- if not inv_obj:
- try:
- inv_obj = CacheInvalidation(key, repo_name)
- Session().add(inv_obj)
- if commit:
- Session().commit()
- except Exception:
- log.error(traceback.format_exc())
- Session().rollback()
- return inv_obj
-
- @classmethod
- def invalidate(cls, key):
- """
- Returns Invalidation object if this given key should be invalidated
- None otherwise. `cache_active = False` means that this cache
- state is not valid and needs to be invalidated
-
- :param key:
+ def set_invalidate(cls, repo_name):
"""
- repo_name = key
- repo_name = remove_suffix(repo_name, '_README')
- repo_name = remove_suffix(repo_name, '_RSS')
- repo_name = remove_suffix(repo_name, '_ATOM')
-
- cache_key = cls._get_cache_key(key)
- inv = cls._get_or_create_inv_obj(cache_key, repo_name)
-
- if inv and not inv.cache_active:
- return inv
-
- @classmethod
- def set_invalidate(cls, key=None, repo_name=None):
+ Mark all caches of a repo as invalid in the database.
"""
- Mark this Cache key for invalidation, either by key or whole
- cache sets based on repo_name
-
- :param key:
- """
- invalidated_keys = []
- if key:
- assert not repo_name
- cache_key = cls._get_cache_key(key)
- inv_objs = Session().query(cls).filter(cls.cache_key == cache_key).all()
- else:
- assert repo_name
- inv_objs = Session().query(cls).filter(cls.cache_args == repo_name).all()
+ inv_objs = Session().query(cls).filter(cls.cache_args == repo_name).all()
try:
for inv_obj in inv_objs:
+ log.debug('marking %s key for invalidation based on repo_name=%s'
+ % (inv_obj, safe_str(repo_name)))
inv_obj.cache_active = False
- log.debug('marking %s key for invalidation based on key=%s,repo_name=%s'
- % (inv_obj, key, safe_str(repo_name)))
- invalidated_keys.append(inv_obj.cache_key)
Session().add(inv_obj)
Session().commit()
except Exception:
log.error(traceback.format_exc())
Session().rollback()
- return invalidated_keys
-
- @classmethod
- def set_valid(cls, key):
- """
- Mark this cache key as active and currently cached
-
- :param key:
- """
- inv_obj = cls.query().filter(cls.cache_key == key).scalar()
- inv_obj.cache_active = True
- Session().add(inv_obj)
- Session().commit()
@classmethod
- def get_cache_map(cls):
-
- class cachemapdict(dict):
+ def test_and_set_valid(cls, repo_name, kind, valid_cache_keys=None):
+ """
+ Mark this cache key as active and currently cached.
+ Return True if the existing cache registration still was valid.
+ Return False to indicate that it had been invalidated and caches should be refreshed.
+ """
- def __init__(self, *args, **kwargs):
- self.fixkey = kwargs.pop('fixkey', False)
- super(cachemapdict, self).__init__(*args, **kwargs)
+ key = (repo_name + '_' + kind) if kind else repo_name
+ cache_key = cls._get_cache_key(key)
+
+ if valid_cache_keys and cache_key in valid_cache_keys:
+ return True
- def __getattr__(self, name):
- cache_key = name
- if self.fixkey:
- cache_key = cls._get_cache_key(name)
- if cache_key in self.__dict__:
- return self.__dict__[cache_key]
- else:
- return self[cache_key]
+ try:
+ inv_obj = cls.query().filter(cls.cache_key == cache_key).scalar()
+ if not inv_obj:
+ inv_obj = CacheInvalidation(cache_key, repo_name)
+ was_valid = inv_obj.cache_active
+ inv_obj.cache_active = True
+ Session().add(inv_obj)
+ Session().commit()
+ return was_valid
+ except Exception:
+ log.error(traceback.format_exc())
+ Session().rollback()
+ return False
- def __getitem__(self, name):
- cache_key = name
- if self.fixkey:
- cache_key = cls._get_cache_key(name)
- try:
- return super(cachemapdict, self).__getitem__(cache_key)
- except KeyError:
- return None
-
- cache_map = cachemapdict(fixkey=True)
- for obj in cls.query().all():
- cache_map[obj.cache_key] = cachemapdict(obj.get_dict())
- return cache_map
+ @classmethod
+ def get_valid_cache_keys(cls):
+ """
+ Return opaque object with information of which caches still are valid
+ and can be used without checking for invalidation.
+ """
+ return set(inv_obj.cache_key for inv_obj in cls.query().filter(cls.cache_active).all())
class ChangesetComment(Base, BaseModel):
@@ -2030,6 +2131,92 @@ class UserNotification(Base, BaseModel):
Session().add(self)
+class Gist(Base, BaseModel):
+ __tablename__ = 'gists'
+ __table_args__ = (
+ Index('g_gist_access_id_idx', 'gist_access_id'),
+ Index('g_created_on_idx', 'created_on'),
+ {'extend_existing': True, 'mysql_engine': 'InnoDB',
+ 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
+ )
+ GIST_PUBLIC = u'public'
+ GIST_PRIVATE = u'private'
+
+ gist_id = Column('gist_id', Integer(), primary_key=True)
+ gist_access_id = Column('gist_access_id', Unicode(250))
+ gist_description = Column('gist_description', UnicodeText(1024))
+ gist_owner = Column('user_id', Integer(), ForeignKey('users.user_id'), nullable=True)
+ gist_expires = Column('gist_expires', Float(), nullable=False)
+ gist_type = Column('gist_type', Unicode(128), nullable=False)
+ created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
+ modified_at = Column('modified_at', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
+
+ owner = relationship('User')
+
+ @classmethod
+ def get_or_404(cls, id_):
+ res = cls.query().filter(cls.gist_access_id == id_).scalar()
+ if not res:
+ raise HTTPNotFound
+ return res
+
+ @classmethod
+ def get_by_access_id(cls, gist_access_id):
+ return cls.query().filter(cls.gist_access_id == gist_access_id).scalar()
+
+ def gist_url(self):
+ import rhodecode
+ alias_url = rhodecode.CONFIG.get('gist_alias_url')
+ if alias_url:
+ return alias_url.replace('{gistid}', self.gist_access_id)
+
+ from pylons import url
+ return url('gist', gist_id=self.gist_access_id, qualified=True)
+
+ @classmethod
+ def base_path(cls):
+ """
+ Returns base path when all gists are stored
+
+ :param cls:
+ """
+ from rhodecode.model.gist import GIST_STORE_LOC
+ q = Session().query(RhodeCodeUi)\
+ .filter(RhodeCodeUi.ui_key == URL_SEP)
+ q = q.options(FromCache("sql_cache_short", "repository_repo_path"))
+ return os.path.join(q.one().ui_value, GIST_STORE_LOC)
+
+ def get_api_data(self):
+ """
+ Common function for generating gist related data for API
+ """
+ gist = self
+ data = dict(
+ gist_id=gist.gist_id,
+ type=gist.gist_type,
+ access_id=gist.gist_access_id,
+ description=gist.gist_description,
+ url=gist.gist_url(),
+ expires=gist.gist_expires,
+ created_on=gist.created_on,
+ )
+ return data
+
+ def __json__(self):
+ data = dict(
+ )
+ data.update(self.get_api_data())
+ return data
+ ## SCM functions
+
+ @property
+ def scm_instance(self):
+ from rhodecode.lib.vcs import get_repo
+ base_path = self.base_path()
+ return get_repo(os.path.join(*map(safe_str,
+ [base_path, self.gist_access_id])))
+
+
class DbMigrateVersion(Base, BaseModel):
__tablename__ = 'db_migrate_version'
__table_args__ = (