##// END OF EJS Templates
notification fixes and improvements
notification fixes and improvements

File last commit:

r1703:f23828b0 beta
r1703:f23828b0 beta
Show More
db.py
1192 lines | 45.1 KiB | text/x-python | PythonLexer
Models code cleanups
r759 # -*- coding: utf-8 -*-
"""
new improved models with helper functions for easier data fetching
r832 rhodecode.model.db
~~~~~~~~~~~~~~~~~~
source code cleanup: remove trailing white space, normalize file endings
r1203
added current db version into rhodecode,...
r834 Database Models for RhodeCode
source code cleanup: remove trailing white space, normalize file endings
r1203
Models code cleanups
r759 :created_on: Apr 08, 2010
:author: marcink
source code cleanup: remove trailing white space, normalize file endings
r1203 :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
Models code cleanups
r759 :license: GPLv3, see COPYING for more details.
"""
fixed license issue #149
r1206 # This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
source code cleanup: remove trailing white space, normalize file endings
r1203 #
Models code cleanups
r759 # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
source code cleanup: remove trailing white space, normalize file endings
r1203 #
Models code cleanups
r759 # You should have received a copy of the GNU General Public License
fixed license issue #149
r1206 # along with this program. If not, see <http://www.gnu.org/licenses/>.
Added os.sep in models for better win support...
r1199
import os
Models code cleanups
r759 import logging
import datetime
fixes #200, rewrote the whole caching mechanism to get rid of such problems. Now cached instances are attached...
r1366 import traceback
Added grouping by days in journal
r994 from datetime import date
Models code cleanups
r759
fixed imports
r658 from sqlalchemy import *
User usermodel instead of db model to manage accounts...
r1634 from sqlalchemy.exc import DatabaseError
fixes #265 ldap save fails sometimes on converting attributes to booleans, added getter and setter...
r1546 from sqlalchemy.ext.hybrid import hybrid_property
fixes #288...
r1594 from sqlalchemy.orm import relationship, joinedload, class_mapper, validates
fixes #200, rewrote the whole caching mechanism to get rid of such problems. Now cached instances are attached...
r1366 from beaker.cache import cache_region, region_invalidate
from vcs import get_backend
from vcs.utils.helpers import get_scm
Extended API...
r1500 from vcs.exceptions import VCSError
fixes #200, rewrote the whole caching mechanism to get rid of such problems. Now cached instances are attached...
r1366 from vcs.utils.lazy import LazyProperty
fixed issues with python2.5...
r1514 from rhodecode.lib import str2bool, safe_str, get_changeset_safe, \
fixes #265 ldap save fails sometimes on converting attributes to booleans, added getter and setter...
r1546 generate_api_key, safe_unicode
removed users_group controller in replace for model methods,...
r1436 from rhodecode.lib.exceptions import UsersGroupsAssignedException
fixed issues with python2.5...
r1514 from rhodecode.lib.compat import json
moved caching query to libs
r1669 from rhodecode.lib.caching_query import FromCache
Extended API...
r1500
fixed Session problems in model class functions...
r1081 from rhodecode.model.meta import Base, Session
moved caching query to libs
r1669
Models code cleanups
r759
fixes #265 ldap save fails sometimes on converting attributes to booleans, added getter and setter...
r1546
Nicolas VINOT
Correct code style
r1593 log = logging.getLogger(__name__)
renamed project to rhodecode
r547
fixed Session problems in model class functions...
r1081 #==============================================================================
Added basic JsonSerialization into models....
r1388 # BASE CLASSES
fixed Session problems in model class functions...
r1081 #==============================================================================
Nicolas VINOT
Correct code style
r1593 class ModelSerializer(json.JSONEncoder):
Added basic JsonSerialization into models....
r1388 """
Simple Serializer for JSON,
Nicolas VINOT
Improve API with user/group/repo CRUD methods
r1584
Added basic JsonSerialization into models....
r1388 usage::
Nicolas VINOT
Improve API with user/group/repo CRUD methods
r1584
Added basic JsonSerialization into models....
r1388 to make object customized for serialization implement a __json__
method that will return a dict for serialization into json
Nicolas VINOT
Improve API with user/group/repo CRUD methods
r1584
Added basic JsonSerialization into models....
r1388 example::
Nicolas VINOT
Improve API with user/group/repo CRUD methods
r1584
Added basic JsonSerialization into models....
r1388 class Task(object):
Nicolas VINOT
Improve API with user/group/repo CRUD methods
r1584
Added basic JsonSerialization into models....
r1388 def __init__(self, name, value):
self.name = name
self.value = value
Nicolas VINOT
Improve API with user/group/repo CRUD methods
r1584
Added basic JsonSerialization into models....
r1388 def __json__(self):
return dict(name=self.name,
Nicolas VINOT
Improve API with user/group/repo CRUD methods
r1584 value=self.value)
Added basic JsonSerialization into models....
r1388 """
Nicolas VINOT
Correct code style
r1593 def default(self, obj):
Added basic JsonSerialization into models....
r1388
Nicolas VINOT
Correct code style
r1593 if hasattr(obj, '__json__'):
Added basic JsonSerialization into models....
r1388 return obj.__json__()
else:
Nicolas VINOT
Correct code style
r1593 return json.JSONEncoder.default(self, obj)
Added basic JsonSerialization into models....
r1388
Nicolas VINOT
Correct code style
r1593 class BaseModel(object):
Added basic JsonSerialization into models....
r1388 """Base Model for all classess
"""
@classmethod
Nicolas VINOT
Correct code style
r1593 def _get_keys(cls):
Added basic JsonSerialization into models....
r1388 """return column names for this model """
Nicolas VINOT
Correct code style
r1593 return class_mapper(cls).c.keys()
Added basic JsonSerialization into models....
r1388
Nicolas VINOT
Correct code style
r1593 def get_dict(self):
Added basic JsonSerialization into models....
r1388 """return dict with keys and values corresponding
to this model data """
d = {}
for k in self._get_keys():
Nicolas VINOT
Correct code style
r1593 d[k] = getattr(self, k)
Added basic JsonSerialization into models....
r1388 return d
Nicolas VINOT
Correct code style
r1593 def get_appstruct(self):
Added basic JsonSerialization into models....
r1388 """return list with keys and values tupples corresponding
to this model data """
l = []
for k in self._get_keys():
Nicolas VINOT
Correct code style
r1593 l.append((k, getattr(self, k),))
Added basic JsonSerialization into models....
r1388 return l
Nicolas VINOT
Correct code style
r1593 def populate_obj(self, populate_dict):
Added basic JsonSerialization into models....
r1388 """populate model with data from given populate_dict"""
for k in self._get_keys():
if k in populate_dict:
Nicolas VINOT
Correct code style
r1593 setattr(self, k, populate_dict[k])
Added basic JsonSerialization into models....
r1388
@classmethod
Nicolas VINOT
Correct code style
r1593 def query(cls):
return Session.query(cls)
Added basic JsonSerialization into models....
r1388
@classmethod
Nicolas VINOT
Correct code style
r1593 def get(cls, id_):
fixes #288...
r1594 if id_:
return cls.query().get(id_)
Code cleanup...
r1466
Added more advanced hook management into rhodecode admin settings
r1460 @classmethod
Nicolas VINOT
Correct code style
r1593 def getAll(cls):
Nicolas VINOT
Improve API with user/group/repo CRUD methods
r1584 return cls.query().all()
Code cleanup...
r1466
Added more advanced hook management into rhodecode admin settings
r1460 @classmethod
Nicolas VINOT
Correct code style
r1593 def delete(cls, id_):
obj = cls.query().get(id_)
Session.delete(obj)
Added more advanced hook management into rhodecode admin settings
r1460 Session.commit()
Code cleanup...
r1466
fixed Session problems in model class functions...
r1081
refactoring of models names for repoGroup permissions
r1633 class RhodeCodeSetting(Base, BaseModel):
renamed hg_app to rhodecode
r548 __tablename__ = 'rhodecode_settings'
Nicolas VINOT
Correct code style
r1593 __table_args__ = (UniqueConstraint('app_settings_name'), {'extend_existing':True})
fixes #288...
r1594 app_settings_id = Column("app_settings_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
app_settings_name = Column("app_settings_name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
_app_settings_value = Column("app_settings_value", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
renamed project to rhodecode
r547
fixes #288...
r1594 def __init__(self, k='', v=''):
Added settings model, and Exceptions lib....
r704 self.app_settings_name = k
self.app_settings_value = v
fixes #265 ldap save fails sometimes on converting attributes to booleans, added getter and setter...
r1546
Nicolas VINOT
Correct code style
r1593 @validates('_app_settings_value')
def validate_settings_value(self, key, val):
assert type(val) == unicode
added validation of params on settings table
r1561 return val
fixes #265 ldap save fails sometimes on converting attributes to booleans, added getter and setter...
r1546 @hybrid_property
Nicolas VINOT
Correct code style
r1593 def app_settings_value(self):
fixes #265 ldap save fails sometimes on converting attributes to booleans, added getter and setter...
r1546 v = self._app_settings_value
if v == 'ldap_active':
Nicolas VINOT
Correct code style
r1593 v = str2bool(v)
Nicolas VINOT
Merge with upstream
r1591 return v
fixes #265 ldap save fails sometimes on converting attributes to booleans, added getter and setter...
r1546
@app_settings_value.setter
Nicolas VINOT
Correct code style
r1593 def app_settings_value(self, val):
fixes #265 ldap save fails sometimes on converting attributes to booleans, added getter and setter...
r1546 """
Setter that will always make sure we use unicode in app_settings_value
Nicolas VINOT
Merge with upstream
r1591
fixes #265 ldap save fails sometimes on converting attributes to booleans, added getter and setter...
r1546 :param val:
"""
Nicolas VINOT
Correct code style
r1593 self._app_settings_value = safe_unicode(val)
fixes #265 ldap save fails sometimes on converting attributes to booleans, added getter and setter...
r1546
Nicolas VINOT
Correct code style
r1593 def __repr__(self):
return "<%s('%s:%s')>" % (self.__class__.__name__,
self.app_settings_name, self.app_settings_value)
Added settings model, and Exceptions lib....
r704
Fixed #161 form saves the create repository permission....
r1266
@classmethod
Nicolas VINOT
Correct code style
r1593 def get_by_name(cls, ldap_key):
Nicolas VINOT
Improve API with user/group/repo CRUD methods
r1584 return cls.query()\
Nicolas VINOT
Correct code style
r1593 .filter(cls.app_settings_name == ldap_key).scalar()
added some fixes to LDAP form re-submition, new simples ldap-settings getter....
r1292
@classmethod
fixes #288...
r1594 def get_app_settings(cls, cache=False):
Fixed #161 form saves the create repository permission....
r1266
Nicolas VINOT
Improve API with user/group/repo CRUD methods
r1584 ret = cls.query()
Fixed #161 form saves the create repository permission....
r1266
if cache:
Nicolas VINOT
Correct code style
r1593 ret = ret.options(FromCache("sql_cache_short", "get_hg_settings"))
Fixed #161 form saves the create repository permission....
r1266
if not ret:
Nicolas VINOT
Correct code style
r1593 raise Exception('Could not get application settings !')
Fixed #161 form saves the create repository permission....
r1266 settings = {}
for each in ret:
settings['rhodecode_' + each.app_settings_name] = \
each.app_settings_value
return settings
@classmethod
fixes #288...
r1594 def get_ldap_settings(cls, cache=False):
Nicolas VINOT
Improve API with user/group/repo CRUD methods
r1584 ret = cls.query()\
Nicolas VINOT
Correct code style
r1593 .filter(cls.app_settings_name.startswith('ldap_')).all()
Fixed #161 form saves the create repository permission....
r1266 fd = {}
for row in ret:
Nicolas VINOT
Correct code style
r1593 fd.update({row.app_settings_name:row.app_settings_value})
fixes #204, ldap active checkbox, credits goes to Matt Little.
r1381
Fixed #161 form saves the create repository permission....
r1266 return fd
Nicolas VINOT
Correct code style
r1593 class RhodeCodeUi(Base, BaseModel):
renamed hg_app to rhodecode
r548 __tablename__ = 'rhodecode_ui'
Nicolas VINOT
Correct code style
r1593 __table_args__ = (UniqueConstraint('ui_key'), {'extend_existing':True})
Added more advanced hook management into rhodecode admin settings
r1460
HOOK_UPDATE = 'changegroup.update'
HOOK_REPO_SIZE = 'changegroup.repo_size'
HOOK_PUSH = 'pretxnchangegroup.push_logger'
HOOK_PULL = 'preoutgoing.pull_logger'
fixes #288...
r1594 ui_id = Column("ui_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
ui_section = Column("ui_section", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
ui_key = Column("ui_key", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
ui_value = Column("ui_value", String(length=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)
Hacking for git support,and new faster repo scan
r631
#47 implemented Adding of new repo_groups+forms+validators. Fixed sorting of repo groups by main names in multiple locations. Removed some unneeded calls to self.sa for exchange to .query() methods....
r1345 @classmethod
Nicolas VINOT
Correct code style
r1593 def get_by_key(cls, key):
return cls.query().filter(cls.ui_key == key)
#47 implemented Adding of new repo_groups+forms+validators. Fixed sorting of repo groups by main names in multiple locations. Removed some unneeded calls to self.sa for exchange to .query() methods....
r1345
Added more advanced hook management into rhodecode admin settings
r1460 @classmethod
Nicolas VINOT
Correct code style
r1593 def get_builtin_hooks(cls):
Added more advanced hook management into rhodecode admin settings
r1460 q = cls.query()
Nicolas VINOT
Correct code style
r1593 q = q.filter(cls.ui_key.in_([cls.HOOK_UPDATE,
Added more advanced hook management into rhodecode admin settings
r1460 cls.HOOK_REPO_SIZE,
Nicolas VINOT
Correct code style
r1593 cls.HOOK_PUSH, cls.HOOK_PULL]))
Added more advanced hook management into rhodecode admin settings
r1460 return q.all()
@classmethod
Nicolas VINOT
Correct code style
r1593 def get_custom_hooks(cls):
Added more advanced hook management into rhodecode admin settings
r1460 q = cls.query()
Nicolas VINOT
Correct code style
r1593 q = q.filter(~cls.ui_key.in_([cls.HOOK_UPDATE,
Added more advanced hook management into rhodecode admin settings
r1460 cls.HOOK_REPO_SIZE,
Nicolas VINOT
Correct code style
r1593 cls.HOOK_PUSH, cls.HOOK_PULL]))
q = q.filter(cls.ui_section == 'hooks')
Added more advanced hook management into rhodecode admin settings
r1460 return q.all()
@classmethod
Nicolas VINOT
Correct code style
r1593 def create_or_update_hook(cls, key, val):
new_ui = cls.get_by_key(key).scalar() or cls()
Added more advanced hook management into rhodecode admin settings
r1460 new_ui.ui_section = 'hooks'
new_ui.ui_active = True
new_ui.ui_key = key
new_ui.ui_value = val
Nicolas VINOT
Correct code style
r1593 Session.add(new_ui)
Added more advanced hook management into rhodecode admin settings
r1460 Session.commit()
Nicolas VINOT
Correct code style
r1593 class User(Base, BaseModel):
renamed project to rhodecode
r547 __tablename__ = 'users'
Nicolas VINOT
Correct code style
r1593 __table_args__ = (UniqueConstraint('username'), UniqueConstraint('email'), {'extend_existing':True})
fixes #288...
r1594 user_id = Column("user_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
username = Column("username", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
password = Column("password", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
active = Column("active", Boolean(), nullable=True, unique=None, default=None)
admin = Column("admin", Boolean(), nullable=True, unique=None, default=False)
name = Column("name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
lastname = Column("lastname", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
email = Column("email", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
last_login = Column("last_login", DateTime(timezone=False), nullable=True, unique=None, default=None)
ldap_dn = Column("ldap_dn", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
api_key = Column("api_key", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
Hacking for git support,and new faster repo scan
r631
fixes #288...
r1594 user_log = relationship('UserLog', cascade='all')
user_perms = relationship('UserToPerm', primaryjoin="User.user_id==UserToPerm.user_id", cascade='all')
Hacking for git support,and new faster repo scan
r631
Nicolas VINOT
Correct code style
r1593 repositories = relationship('Repository')
fixes #288...
r1594 user_followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_user_id==User.user_id', cascade='all')
refactoring of models names for repoGroup permissions
r1633 repo_to_perm = relationship('UserRepoToPerm', primaryjoin='UserRepoToPerm.user_id==User.user_id', cascade='all')
fixed #72 show warning on removal when user still is owner of existing repositories...
r713
fixes #288...
r1594 group_member = relationship('UsersGroupMember', cascade='all')
Moved BaseModel into base class for declarative base. Added some handy methods into...
r1065
#302 - basic notification system, models+tests
r1702 notifications = relationship('Notification', secondary='user_to_notification')
Models code cleanups
r759 @property
Nicolas VINOT
Correct code style
r1593 def full_contact(self):
return '%s %s <%s>' % (self.name, self.lastname, self.email)
Hacking for git support,and new faster repo scan
r631
Added some more details into user edit permissions view
r895 @property
Nicolas VINOT
Correct code style
r1593 def short_contact(self):
return '%s %s' % (self.name, self.lastname)
made simple global rss and atom feed
r1088
@property
Nicolas VINOT
Correct code style
r1593 def is_admin(self):
Added some more details into user edit permissions view
r895 return self.admin
Nicolas VINOT
Correct code style
r1593 def __repr__(self):
Simplified last_login call on user, and changed login to use User model directly
r1400 try:
Nicolas VINOT
Correct code style
r1593 return "<%s('id:%s:%s')>" % (self.__class__.__name__,
self.user_id, self.username)
Simplified last_login call on user, and changed login to use User model directly
r1400 except:
return self.__class__.__name__
Hacking for git support,and new faster repo scan
r631
Moved BaseModel into base class for declarative base. Added some handy methods into...
r1065 @classmethod
Added cache options to some db getters
r1665 def get_by_username(cls, username, case_insensitive=False, cache=False):
Simplified last_login call on user, and changed login to use User model directly
r1400 if case_insensitive:
Added cache options to some db getters
r1665 q = cls.query().filter(cls.username.ilike(username))
Simplified last_login call on user, and changed login to use User model directly
r1400 else:
Added cache options to some db getters
r1665 q = cls.query().filter(cls.username == username)
if cache:
q = q.options(FromCache("sql_cache_short",
"get_user_%s" % username))
return q.scalar()
Moved BaseModel into base class for declarative base. Added some handy methods into...
r1065
fixes #223 improve password reset form
r1417 @classmethod
Added cache options to some db getters
r1665 def get_by_api_key(cls, api_key, cache=False):
q = cls.query().filter(cls.api_key == api_key)
if cache:
q = q.options(FromCache("sql_cache_short",
"get_api_key_%s" % api_key))
fix for api key lookup, reuse same function in user model
r1693 return q.scalar()
fixes #223 improve password reset form
r1417
Nicolas VINOT
Correct code style
r1593 def update_lastlogin(self):
renamed project to rhodecode
r547 """Update user lastlogin"""
Hacking for git support,and new faster repo scan
r631
Simplified last_login call on user, and changed login to use User model directly
r1400 self.last_login = datetime.datetime.now()
Nicolas VINOT
Correct code style
r1593 Session.add(self)
Simplified last_login call on user, and changed login to use User model directly
r1400 Session.commit()
Nicolas VINOT
Correct code style
r1593 log.debug('updated user %s lastlogin', self.username)
Hacking for git support,and new faster repo scan
r631
Nicolas VINOT
Correct code style
r1593 class UserLog(Base, BaseModel):
renamed project to rhodecode
r547 __tablename__ = 'user_logs'
Bumped sqlalchemy version to 0.7, replaced timerproxy with new event system for sqlalchemy....
r1360 __table_args__ = {'extend_existing':True}
fixes #288...
r1594 user_log_id = Column("user_log_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)
repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
repository_name = Column("repository_name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
user_ip = Column("user_ip", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
action = Column("action", UnicodeText(length=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)
Hacking for git support,and new faster repo scan
r631
Added grouping by days in journal
r994 @property
Nicolas VINOT
Correct code style
r1593 def action_as_day(self):
return date(*self.action_date.timetuple()[:3])
Added grouping by days in journal
r994
Nicolas VINOT
Correct code style
r1593 user = relationship('User')
repository = relationship('Repository')
Hacking for git support,and new faster repo scan
r631
started working on issue #56
r956
Nicolas VINOT
Correct code style
r1593 class UsersGroup(Base, BaseModel):
started working on issue #56
r956 __tablename__ = 'users_groups'
Bumped sqlalchemy version to 0.7, replaced timerproxy with new event system for sqlalchemy....
r1360 __table_args__ = {'extend_existing':True}
started working on issue #56
r956
fixes #288...
r1594 users_group_id = Column("users_group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
users_group_name = Column("users_group_name", String(length=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)
started working on issue #56
r956
fixes #288...
r1594 members = relationship('UsersGroupMember', cascade="all, delete, delete-orphan", lazy="joined")
started working on issue #56
r956
Nicolas VINOT
Correct code style
r1593 def __repr__(self):
return '<userGroup(%s)>' % (self.users_group_name)
Fixed permissions for users groups, group can have create repo permission now....
r1271
@classmethod
fixes #288...
r1594 def get_by_group_name(cls, group_name, cache=False, case_insensitive=False):
Fixed permissions for users groups, group can have create repo permission now....
r1271 if case_insensitive:
Nicolas VINOT
Improve API with user/group/repo CRUD methods
r1584 gr = cls.query()\
Nicolas VINOT
Correct code style
r1593 .filter(cls.users_group_name.ilike(group_name))
Fixed permissions for users groups, group can have create repo permission now....
r1271 else:
Nicolas VINOT
Improve API with user/group/repo CRUD methods
r1584 gr = cls.query()\
Nicolas VINOT
Correct code style
r1593 .filter(cls.users_group_name == group_name)
Fixed permissions for users groups, group can have create repo permission now....
r1271 if cache:
Nicolas VINOT
Correct code style
r1593 gr = gr.options(FromCache("sql_cache_short",
"get_user_%s" % group_name))
Fixed permissions for users groups, group can have create repo permission now....
r1271 return gr.scalar()
removed users_group controller in replace for model methods,...
r1436
@classmethod
fixes #288...
r1594 def get(cls, users_group_id, cache=False):
Nicolas VINOT
Improve API with user/group/repo CRUD methods
r1584 users_group = cls.query()
removed users_group controller in replace for model methods,...
r1436 if cache:
Nicolas VINOT
Correct code style
r1593 users_group = users_group.options(FromCache("sql_cache_short",
"get_users_group_%s" % users_group_id))
return users_group.get(users_group_id)
removed users_group controller in replace for model methods,...
r1436
@classmethod
Nicolas VINOT
Correct code style
r1593 def create(cls, form_data):
removed users_group controller in replace for model methods,...
r1436 try:
new_users_group = cls()
for k, v in form_data.items():
Nicolas VINOT
Correct code style
r1593 setattr(new_users_group, k, v)
removed users_group controller in replace for model methods,...
r1436
Nicolas VINOT
Correct code style
r1593 Session.add(new_users_group)
removed users_group controller in replace for model methods,...
r1436 Session.commit()
Extended API...
r1500 return new_users_group
removed users_group controller in replace for model methods,...
r1436 except:
Nicolas VINOT
Correct code style
r1593 log.error(traceback.format_exc())
removed users_group controller in replace for model methods,...
r1436 Session.rollback()
raise
@classmethod
Nicolas VINOT
Correct code style
r1593 def update(cls, users_group_id, form_data):
removed users_group controller in replace for model methods,...
r1436
try:
fixes #288...
r1594 users_group = cls.get(users_group_id, cache=False)
removed users_group controller in replace for model methods,...
r1436
for k, v in form_data.items():
if k == 'users_group_members':
users_group.members = []
Session.flush()
members_list = []
if v:
Proper patch for issue #276
r1577 v = [v] if isinstance(v, basestring) else v
for u_id in set(v):
Nicolas VINOT
Correct code style
r1593 member = UsersGroupMember(users_group_id, u_id)
members_list.append(member)
setattr(users_group, 'members', members_list)
setattr(users_group, k, v)
removed users_group controller in replace for model methods,...
r1436
Nicolas VINOT
Correct code style
r1593 Session.add(users_group)
removed users_group controller in replace for model methods,...
r1436 Session.commit()
except:
Nicolas VINOT
Correct code style
r1593 log.error(traceback.format_exc())
removed users_group controller in replace for model methods,...
r1436 Session.rollback()
raise
@classmethod
Nicolas VINOT
Correct code style
r1593 def delete(cls, users_group_id):
removed users_group controller in replace for model methods,...
r1436 try:
# check if this group is not assigned to repo
assigned_groups = UsersGroupRepoToPerm.query()\
Nicolas VINOT
Correct code style
r1593 .filter(UsersGroupRepoToPerm.users_group_id ==
users_group_id).all()
removed users_group controller in replace for model methods,...
r1436
if assigned_groups:
refactoring of models names for repoGroup permissions
r1633 raise UsersGroupsAssignedException('RepoGroup assigned to %s' %
Nicolas VINOT
Correct code style
r1593 assigned_groups)
removed users_group controller in replace for model methods,...
r1436
fixes #288...
r1594 users_group = cls.get(users_group_id, cache=False)
Nicolas VINOT
Correct code style
r1593 Session.delete(users_group)
removed users_group controller in replace for model methods,...
r1436 Session.commit()
except:
Nicolas VINOT
Correct code style
r1593 log.error(traceback.format_exc())
removed users_group controller in replace for model methods,...
r1436 Session.rollback()
raise
Nicolas VINOT
Correct code style
r1593 class UsersGroupMember(Base, BaseModel):
started working on issue #56
r956 __tablename__ = 'users_groups_members'
Bumped sqlalchemy version to 0.7, replaced timerproxy with new event system for sqlalchemy....
r1360 __table_args__ = {'extend_existing':True}
started working on issue #56
r956
fixes #288...
r1594 users_group_member_id = Column("users_group_member_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
started working on issue #56
r956
fixes #288...
r1594 user = relationship('User', lazy='joined')
Nicolas VINOT
Correct code style
r1593 users_group = relationship('UsersGroup')
#56 implemented users groups editing,...
r972
fixes #288...
r1594 def __init__(self, gr_id='', u_id=''):
#56 implemented users groups editing,...
r972 self.users_group_id = gr_id
self.user_id = u_id
started working on issue #56
r956
Nicolas VINOT
Implement all CRUD API operation for repo
r1587 @staticmethod
Nicolas VINOT
Correct code style
r1593 def add_user_to_group(group, user):
Nicolas VINOT
Implement all CRUD API operation for repo
r1587 ugm = UsersGroupMember()
ugm.users_group = group
ugm.user = user
Nicolas VINOT
Correct code style
r1593 Session.add(ugm)
Nicolas VINOT
Implement all CRUD API operation for repo
r1587 Session.commit()
return ugm
Nicolas VINOT
Correct code style
r1593 class Repository(Base, BaseModel):
renamed project to rhodecode
r547 __tablename__ = 'repositories'
Nicolas VINOT
Correct code style
r1593 __table_args__ = (UniqueConstraint('repo_name'), {'extend_existing':True},)
fixed Session problems in model class functions...
r1081
fixes #288...
r1594 repo_id = Column("repo_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
repo_name = Column("repo_name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None)
clone_uri = Column("clone_uri", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=False, default=None)
repo_type = Column("repo_type", String(length=255, convert_unicode=False, assert_unicode=None), nullable=False, unique=False, default='hg')
user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
private = Column("private", Boolean(), nullable=True, unique=None, default=None)
enable_statistics = Column("statistics", Boolean(), nullable=True, unique=None, default=True)
enable_downloads = Column("downloads", Boolean(), nullable=True, unique=None, default=True)
description = Column("description", String(length=10000, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
created_on = Column('created_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
Added simple forks page, resolves issue #179
r1301
fixes #288...
r1594 fork_id = Column("fork_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=False, default=None)
group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=False, default=None)
Hacking for git support,and new faster repo scan
r631
added clone_uri,api_key into models. Fixed models for mysql compatibilty
r1113
Nicolas VINOT
Correct code style
r1593 user = relationship('User')
fixes #288...
r1594 fork = relationship('Repository', remote_side=repo_id)
refactoring of models names for repoGroup permissions
r1633 group = relationship('RepoGroup')
repo_to_perm = relationship('UserRepoToPerm', cascade='all', order_by='UserRepoToPerm.repo_to_perm_id')
fixes #288...
r1594 users_group_to_perm = relationship('UsersGroupRepoToPerm', cascade='all')
stats = relationship('Statistics', cascade='all', uselist=False)
fixes #51 deleting a repo didn't delete it's dependent db entries....
r667
fixes #288...
r1594 followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_repo_id==Repository.repo_id', cascade='all')
implemented user dashboards, and following system.
r734
fixes #288...
r1594 logs = relationship('UserLog', cascade='all')
fixees for #106 relation issues on databases different than sqlite
r970
Nicolas VINOT
Correct code style
r1593 def __repr__(self):
return "<%s('%s:%s')>" % (self.__class__.__name__,
self.repo_id, self.repo_name)
Extended repo2db mapper with group creation via directory structures...
r878
Moved BaseModel into base class for declarative base. Added some handy methods into...
r1065 @classmethod
Nicolas VINOT
Correct code style
r1593 def url_sep(cls):
fixes #245 Rescan of the repositories on Windows
r1554 return '/'
Moved BaseModel into base class for declarative base. Added some handy methods into...
r1065
fixes #245 Rescan of the repositories on Windows
r1554 @classmethod
Nicolas VINOT
Correct code style
r1593 def get_by_repo_name(cls, repo_name):
q = Session.query(cls).filter(cls.repo_name == repo_name)
q = q.options(joinedload(Repository.fork))\
.options(joinedload(Repository.user))\
.options(joinedload(Repository.group))
fixes #200, rewrote the whole caching mechanism to get rid of such problems. Now cached instances are attached...
r1366 return q.one()
Added simple forks page, resolves issue #179
r1301
@classmethod
Nicolas VINOT
Correct code style
r1593 def get_repo_forks(cls, repo_id):
return cls.query().filter(Repository.fork_id == repo_id)
Added simple forks page, resolves issue #179
r1301
API added checks for a valid repository on pull command...
r1508 @classmethod
Nicolas VINOT
Correct code style
r1593 def base_path(cls):
API added checks for a valid repository on pull command...
r1508 """
Returns base path when all repos are stored
Nicolas VINOT
Implement all CRUD API operation for repo
r1587
API added checks for a valid repository on pull command...
r1508 :param cls:
"""
Nicolas VINOT
Correct code style
r1593 q = Session.query(RhodeCodeUi).filter(RhodeCodeUi.ui_key ==
cls.url_sep())
q.options(FromCache("sql_cache_short", "repository_repo_path"))
API added checks for a valid repository on pull command...
r1508 return q.one().ui_value
added clone_uri,api_key into models. Fixed models for mysql compatibilty
r1113 @property
Nicolas VINOT
Correct code style
r1593 def just_name(self):
return self.repo_name.split(Repository.url_sep())[-1]
Added handy methods to Repository model for fetching groups with parents
r1155
@property
Nicolas VINOT
Correct code style
r1593 def groups_with_parents(self):
Added handy methods to Repository model for fetching groups with parents
r1155 groups = []
if self.group is None:
return groups
cur_gr = self.group
Nicolas VINOT
Correct code style
r1593 groups.insert(0, cur_gr)
Added handy methods to Repository model for fetching groups with parents
r1155 while 1:
Nicolas VINOT
Correct code style
r1593 gr = getattr(cur_gr, 'parent_group', None)
Added handy methods to Repository model for fetching groups with parents
r1155 cur_gr = cur_gr.parent_group
if gr is None:
break
Nicolas VINOT
Correct code style
r1593 groups.insert(0, gr)
Added handy methods to Repository model for fetching groups with parents
r1155
return groups
@property
Nicolas VINOT
Correct code style
r1593 def groups_and_repo(self):
Added handy methods to Repository model for fetching groups with parents
r1155 return self.groups_with_parents, self.just_name
added clone_uri,api_key into models. Fixed models for mysql compatibilty
r1113
fixes #200, rewrote the whole caching mechanism to get rid of such problems. Now cached instances are attached...
r1366 @LazyProperty
Nicolas VINOT
Correct code style
r1593 def repo_path(self):
fixes #200, rewrote the whole caching mechanism to get rid of such problems. Now cached instances are attached...
r1366 """
Returns base full path for that repository means where it actually
exists on a filesystem
"""
Nicolas VINOT
Correct code style
r1593 q = Session.query(RhodeCodeUi).filter(RhodeCodeUi.ui_key ==
Repository.url_sep())
q.options(FromCache("sql_cache_short", "repository_repo_path"))
adde short cache for repo_path
r1368 return q.one().ui_value
fixes #200, rewrote the whole caching mechanism to get rid of such problems. Now cached instances are attached...
r1366
@property
Nicolas VINOT
Correct code style
r1593 def repo_full_path(self):
fixes #200, rewrote the whole caching mechanism to get rid of such problems. Now cached instances are attached...
r1366 p = [self.repo_path]
# we need to split the name by / since this is how we store the
# names in the database, but that eventually needs to be converted
# into a valid system path
Nicolas VINOT
Correct code style
r1593 p += self.repo_name.split(Repository.url_sep())
return os.path.join(*p)
fixes #200, rewrote the whole caching mechanism to get rid of such problems. Now cached instances are attached...
r1366
Nicolas VINOT
Correct code style
r1593 def get_new_name(self, repo_name):
fixes #260 Put repo in group, then move group to another group -> repo becomes unavailable
r1539 """
returns new full repository name based on assigned group and new new
Nicolas VINOT
Merge with upstream
r1591
fixes #260 Put repo in group, then move group to another group -> repo becomes unavailable
r1539 :param group_name:
"""
path_prefix = self.group.full_path_splitted if self.group else []
Nicolas VINOT
Correct code style
r1593 return Repository.url_sep().join(path_prefix + [repo_name])
fixes #260 Put repo in group, then move group to another group -> repo becomes unavailable
r1539
fixes #200, rewrote the whole caching mechanism to get rid of such problems. Now cached instances are attached...
r1366 @property
Nicolas VINOT
Correct code style
r1593 def _ui(self):
fixes #200, rewrote the whole caching mechanism to get rid of such problems. Now cached instances are attached...
r1366 """
Creates an db based ui object for this repository
"""
from mercurial import ui
from mercurial import config
baseui = ui.ui()
#clean the baseui object
baseui._ocfg = config.config()
baseui._ucfg = config.config()
baseui._tcfg = config.config()
Nicolas VINOT
Improve API with user/group/repo CRUD methods
r1584 ret = RhodeCodeUi.query()\
Nicolas VINOT
Correct code style
r1593 .options(FromCache("sql_cache_short", "repository_repo_ui")).all()
fixes #200, rewrote the whole caching mechanism to get rid of such problems. Now cached instances are attached...
r1366
hg_ui = ret
for ui_ in hg_ui:
if ui_.ui_active:
Nicolas VINOT
Correct code style
r1593 log.debug('settings ui from db[%s]%s:%s', ui_.ui_section,
ui_.ui_key, ui_.ui_value)
baseui.setconfig(ui_.ui_section, ui_.ui_key, ui_.ui_value)
fixes #200, rewrote the whole caching mechanism to get rid of such problems. Now cached instances are attached...
r1366
return baseui
API added checks for a valid repository on pull command...
r1508 @classmethod
Nicolas VINOT
Correct code style
r1593 def is_valid(cls, repo_name):
API added checks for a valid repository on pull command...
r1508 """
returns True if given repo name is a valid filesystem repository
Nicolas VINOT
Implement all CRUD API operation for repo
r1587
API added checks for a valid repository on pull command...
r1508 @param cls:
@param repo_name:
"""
from rhodecode.lib.utils import is_valid_repo
Nicolas VINOT
Correct code style
r1593 return is_valid_repo(repo_name, cls.base_path())
API added checks for a valid repository on pull command...
r1508
fixes #200, rewrote the whole caching mechanism to get rid of such problems. Now cached instances are attached...
r1366 #==========================================================================
Code cleanup...
r1466 # SCM PROPERTIES
#==========================================================================
Nicolas VINOT
Correct code style
r1593 def get_changeset(self, rev):
return get_changeset_safe(self.scm_instance, rev)
Code cleanup...
r1466
@property
Nicolas VINOT
Correct code style
r1593 def tip(self):
return self.get_changeset('tip')
Code cleanup...
r1466
@property
Nicolas VINOT
Correct code style
r1593 def author(self):
Code cleanup...
r1466 return self.tip.author
@property
Nicolas VINOT
Correct code style
r1593 def last_change(self):
Code cleanup...
r1466 return self.scm_instance.last_change
#==========================================================================
fixes #200, rewrote the whole caching mechanism to get rid of such problems. Now cached instances are attached...
r1366 # SCM CACHE INSTANCE
#==========================================================================
@property
Nicolas VINOT
Correct code style
r1593 def invalidate(self):
Cached readme generation...
r1607 return CacheInvalidation.invalidate(self.repo_name)
fixes #200, rewrote the whole caching mechanism to get rid of such problems. Now cached instances are attached...
r1366
Nicolas VINOT
Correct code style
r1593 def set_invalidate(self):
fixes #200, rewrote the whole caching mechanism to get rid of such problems. Now cached instances are attached...
r1366 """
set a cache for invalidation for this instance
"""
Cached readme generation...
r1607 CacheInvalidation.set_invalidate(self.repo_name)
fixes #200, rewrote the whole caching mechanism to get rid of such problems. Now cached instances are attached...
r1366
Code cleanup...
r1466 @LazyProperty
Nicolas VINOT
Correct code style
r1593 def scm_instance(self):
Simplified last_login call on user, and changed login to use User model directly
r1400 return self.__get_instance()
fixes #200, rewrote the whole caching mechanism to get rid of such problems. Now cached instances are attached...
r1366
@property
Nicolas VINOT
Correct code style
r1593 def scm_instance_cached(self):
@cache_region('long_term')
def _c(repo_name):
Simplified last_login call on user, and changed login to use User model directly
r1400 return self.__get_instance()
Cached readme generation...
r1607 rn = self.repo_name
fixed some issues with cache invalidation, and simplified invalidation codes
r1428
fixes #200, rewrote the whole caching mechanism to get rid of such problems. Now cached instances are attached...
r1366 inv = self.invalidate
fixed a bug in cache invalidation
r1427 if inv is not None:
Nicolas VINOT
Correct code style
r1593 region_invalidate(_c, None, rn)
fixed some issues with cache invalidation, and simplified invalidation codes
r1428 # update our cache
Cached readme generation...
r1607 CacheInvalidation.set_valid(inv.cache_key)
Nicolas VINOT
Correct code style
r1593 return _c(rn)
fixes #200, rewrote the whole caching mechanism to get rid of such problems. Now cached instances are attached...
r1366
Nicolas VINOT
Correct code style
r1593 def __get_instance(self):
adde short cache for repo_path
r1368
repo_full_path = self.repo_full_path
fixes #200, rewrote the whole caching mechanism to get rid of such problems. Now cached instances are attached...
r1366 try:
Nicolas VINOT
Correct code style
r1593 alias = get_scm(repo_full_path)[0]
log.debug('Creating instance of %s repository', alias)
backend = get_backend(alias)
fixes #200, rewrote the whole caching mechanism to get rid of such problems. Now cached instances are attached...
r1366 except VCSError:
Nicolas VINOT
Correct code style
r1593 log.error(traceback.format_exc())
log.error('Perhaps this repository is in db and not in '
fixes #200, rewrote the whole caching mechanism to get rid of such problems. Now cached instances are attached...
r1366 'filesystem run rescan repositories with '
Nicolas VINOT
Correct code style
r1593 '"destroy old data " option from admin panel')
fixes #200, rewrote the whole caching mechanism to get rid of such problems. Now cached instances are attached...
r1366 return
if alias == 'hg':
Unicode fixes, added safe_str method for global str() operations +better test sandboxing
r1401
fixes #288...
r1594 repo = backend(safe_str(repo_full_path), create=False,
baseui=self._ui)
Cached readme generation...
r1607 # skip hidden web repository
fixes #200, rewrote the whole caching mechanism to get rid of such problems. Now cached instances are attached...
r1366 if repo._get_hidden():
return
else:
fixes #288...
r1594 repo = backend(repo_full_path, create=False)
fixes #200, rewrote the whole caching mechanism to get rid of such problems. Now cached instances are attached...
r1366
return repo
Moved BaseModel into base class for declarative base. Added some handy methods into...
r1065
refactoring of models names for repoGroup permissions
r1633 class RepoGroup(Base, BaseModel):
Extended repo2db mapper with group creation via directory structures...
r878 __tablename__ = 'groups'
Nicolas VINOT
Correct code style
r1593 __table_args__ = (UniqueConstraint('group_name', 'group_parent_id'),
CheckConstraint('group_id != group_parent_id'), {'extend_existing':True},)
#47 implemented basic gui for browsing repo groups
r1343 __mapper_args__ = {'order_by':'group_name'}
Extended repo2db mapper with group creation via directory structures...
r878
fixes #288...
r1594 group_id = Column("group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
group_name = Column("group_name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None)
group_parent_id = Column("group_parent_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=None, default=None)
group_description = Column("group_description", String(length=10000, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
Extended repo2db mapper with group creation via directory structures...
r878
refactoring of models names for repoGroup permissions
r1633 parent_group = relationship('RepoGroup', remote_side=group_id)
Extended repo2db mapper with group creation via directory structures...
r878
fixes #288...
r1594 def __init__(self, group_name='', parent_group=None):
Extended repo2db mapper with group creation via directory structures...
r878 self.group_name = group_name
self.parent_group = parent_group
Nicolas VINOT
Correct code style
r1593 def __repr__(self):
return "<%s('%s:%s')>" % (self.__class__.__name__, self.group_id,
self.group_name)
Hacking for git support,and new faster repo scan
r631
#47 implemented deleting of empty groups. Fixed problem with full paths on nested groups
r1346 @classmethod
Nicolas VINOT
Correct code style
r1593 def groups_choices(cls):
unified generation of repo groups choices...
r1547 from webhelpers.html import literal as _literal
Nicolas VINOT
Correct code style
r1593 repo_groups = [('', '')]
unified generation of repo groups choices...
r1547 sep = ' &raquo; '
Nicolas VINOT
Correct code style
r1593 _name = lambda k: _literal(sep.join(k))
unified generation of repo groups choices...
r1547
Nicolas VINOT
Correct code style
r1593 repo_groups.extend([(x.group_id, _name(x.full_path_splitted))
for x in cls.query().all()])
Nicolas VINOT
Merge with upstream
r1591
fixes #288...
r1594 repo_groups = sorted(repo_groups, key=lambda t: t[1].split(sep)[0])
unified generation of repo groups choices...
r1547 return repo_groups
Nicolas VINOT
Merge with upstream
r1591
unified generation of repo groups choices...
r1547 @classmethod
Nicolas VINOT
Correct code style
r1593 def url_sep(cls):
#47 implemented deleting of empty groups. Fixed problem with full paths on nested groups
r1346 return '/'
implements #226 repo groups available by path...
r1538 @classmethod
fixes #288...
r1594 def get_by_group_name(cls, group_name, cache=False, case_insensitive=False):
Nicolas VINOT
Improve API with user/group/repo CRUD methods
r1584 if case_insensitive:
gr = cls.query()\
Nicolas VINOT
Correct code style
r1593 .filter(cls.group_name.ilike(group_name))
Nicolas VINOT
Improve API with user/group/repo CRUD methods
r1584 else:
gr = cls.query()\
Nicolas VINOT
Correct code style
r1593 .filter(cls.group_name == group_name)
Nicolas VINOT
Improve API with user/group/repo CRUD methods
r1584 if cache:
Nicolas VINOT
Correct code style
r1593 gr = gr.options(FromCache("sql_cache_short",
"get_group_%s" % group_name))
Nicolas VINOT
Improve API with user/group/repo CRUD methods
r1584 return gr.scalar()
implements #226 repo groups available by path...
r1538
Changes for repo groups
r1159 @property
Nicolas VINOT
Correct code style
r1593 def parents(self):
#209 Added recursive count on repositories to calculate all repos within all nested groups
r1385 parents_recursion_limit = 5
Changes for repo groups
r1159 groups = []
if self.parent_group is None:
return groups
cur_gr = self.parent_group
Nicolas VINOT
Correct code style
r1593 groups.insert(0, cur_gr)
#47 added editing of groups, and moving them between. Added check constraint for groups...
r1349 cnt = 0
Changes for repo groups
r1159 while 1:
#47 added editing of groups, and moving them between. Added check constraint for groups...
r1349 cnt += 1
Nicolas VINOT
Correct code style
r1593 gr = getattr(cur_gr, 'parent_group', None)
Changes for repo groups
r1159 cur_gr = cur_gr.parent_group
if gr is None:
break
#209 Added recursive count on repositories to calculate all repos within all nested groups
r1385 if cnt == parents_recursion_limit:
#47 added editing of groups, and moving them between. Added check constraint for groups...
r1349 # this will prevent accidental infinit loops
Nicolas VINOT
Correct code style
r1593 log.error('group nested more than %s' %
parents_recursion_limit)
#47 added editing of groups, and moving them between. Added check constraint for groups...
r1349 break
Nicolas VINOT
Correct code style
r1593 groups.insert(0, gr)
Changes for repo groups
r1159 return groups
#209 Added recursive count on repositories to calculate all repos within all nested groups
r1385 @property
Nicolas VINOT
Correct code style
r1593 def children(self):
refactoring of models names for repoGroup permissions
r1633 return RepoGroup.query().filter(RepoGroup.parent_group == self)
fixed saving settings on repositories inside groups, also fixes #187...
r1323
@property
Nicolas VINOT
Correct code style
r1593 def name(self):
refactoring of models names for repoGroup permissions
r1633 return self.group_name.split(RepoGroup.url_sep())[-1]
implements #226 repo groups available by path...
r1538
@property
Nicolas VINOT
Correct code style
r1593 def full_path(self):
fixes #288...
r1594 return self.group_name
implements #226 repo groups available by path...
r1538
@property
Nicolas VINOT
Correct code style
r1593 def full_path_splitted(self):
refactoring of models names for repoGroup permissions
r1633 return self.group_name.split(RepoGroup.url_sep())
fixed saving settings on repositories inside groups, also fixes #187...
r1323
Added repo group page showing what reposiories are inside a group
r1193 @property
Nicolas VINOT
Correct code style
r1593 def repositories(self):
return Repository.query().filter(Repository.group == self)
Added repo group page showing what reposiories are inside a group
r1193
#209 Added recursive count on repositories to calculate all repos within all nested groups
r1385 @property
Nicolas VINOT
Correct code style
r1593 def repositories_recursive_count(self):
#209 Added recursive count on repositories to calculate all repos within all nested groups
r1385 cnt = self.repositories.count()
Nicolas VINOT
Correct code style
r1593 def children_count(group):
#209 Added recursive count on repositories to calculate all repos within all nested groups
r1385 cnt = 0
for child in group.children:
cnt += child.repositories.count()
Nicolas VINOT
Correct code style
r1593 cnt += children_count(child)
#209 Added recursive count on repositories to calculate all repos within all nested groups
r1385 return cnt
Nicolas VINOT
Correct code style
r1593 return cnt + children_count(self)
#209 Added recursive count on repositories to calculate all repos within all nested groups
r1385
implements #226 repo groups available by path...
r1538
Nicolas VINOT
Correct code style
r1593 def get_new_name(self, group_name):
implements #226 repo groups available by path...
r1538 """
returns new full group name based on parent and new name
Nicolas VINOT
Merge with upstream
r1591
implements #226 repo groups available by path...
r1538 :param group_name:
"""
Cached readme generation...
r1607 path_prefix = (self.parent_group.full_path_splitted if
fixes #288...
r1594 self.parent_group else [])
refactoring of models names for repoGroup permissions
r1633 return RepoGroup.url_sep().join(path_prefix + [group_name])
implements #226 repo groups available by path...
r1538
Nicolas VINOT
Correct code style
r1593 class Permission(Base, BaseModel):
renamed project to rhodecode
r547 __tablename__ = 'permissions'
Bumped sqlalchemy version to 0.7, replaced timerproxy with new event system for sqlalchemy....
r1360 __table_args__ = {'extend_existing':True}
fixes #288...
r1594 permission_id = Column("permission_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
permission_name = Column("permission_name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
permission_longname = Column("permission_longname", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
Hacking for git support,and new faster repo scan
r631
Nicolas VINOT
Correct code style
r1593 def __repr__(self):
return "<%s('%s:%s')>" % (self.__class__.__name__,
self.permission_id, self.permission_name)
renamed project to rhodecode
r547
Fixed #161 form saves the create repository permission....
r1266 @classmethod
Nicolas VINOT
Correct code style
r1593 def get_by_key(cls, key):
return cls.query().filter(cls.permission_name == key).scalar()
Fixed #161 form saves the create repository permission....
r1266
refactoring of models names for repoGroup permissions
r1633 class UserRepoToPerm(Base, BaseModel):
renamed project to rhodecode
r547 __tablename__ = 'repo_to_perm'
Nicolas VINOT
Correct code style
r1593 __table_args__ = (UniqueConstraint('user_id', 'repository_id'), {'extend_existing':True})
fixes #288...
r1594 repo_to_perm_id = Column("repo_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)
repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
Hacking for git support,and new faster repo scan
r631
Nicolas VINOT
Correct code style
r1593 user = relationship('User')
permission = relationship('Permission')
repository = relationship('Repository')
renamed project to rhodecode
r547
Nicolas VINOT
Correct code style
r1593 class UserToPerm(Base, BaseModel):
renamed project to rhodecode
r547 __tablename__ = 'user_to_perm'
Nicolas VINOT
Correct code style
r1593 __table_args__ = (UniqueConstraint('user_id', 'permission_id'), {'extend_existing':True})
fixes #288...
r1594 user_to_perm_id = Column("user_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)
Hacking for git support,and new faster repo scan
r631
Nicolas VINOT
Correct code style
r1593 user = relationship('User')
permission = relationship('Permission')
renamed project to rhodecode
r547
Fixed #161 form saves the create repository permission....
r1266 @classmethod
Nicolas VINOT
Correct code style
r1593 def has_perm(cls, user_id, perm):
if not isinstance(perm, Permission):
raise Exception('perm needs to be an instance of Permission class')
Fixed #161 form saves the create repository permission....
r1266
Nicolas VINOT
Correct code style
r1593 return cls.query().filter(cls.user_id == user_id)\
.filter(cls.permission == perm).scalar() is not None
Fixed #161 form saves the create repository permission....
r1266
@classmethod
Nicolas VINOT
Correct code style
r1593 def grant_perm(cls, user_id, perm):
if not isinstance(perm, Permission):
raise Exception('perm needs to be an instance of Permission class')
Fixed #161 form saves the create repository permission....
r1266
new = cls()
new.user_id = user_id
new.permission = perm
try:
Nicolas VINOT
Correct code style
r1593 Session.add(new)
Fixed #161 form saves the create repository permission....
r1266 Session.commit()
except:
Session.rollback()
@classmethod
Nicolas VINOT
Correct code style
r1593 def revoke_perm(cls, user_id, perm):
if not isinstance(perm, Permission):
raise Exception('perm needs to be an instance of Permission class')
Fixed #161 form saves the create repository permission....
r1266
try:
Nicolas VINOT
Correct code style
r1593 cls.query().filter(cls.user_id == user_id)\
.filter(cls.permission == perm).delete()
Fixed #161 form saves the create repository permission....
r1266 Session.commit()
except:
Session.rollback()
#56 added assignments of users groups into repository
r1014
Nicolas VINOT
Correct code style
r1593 class UsersGroupRepoToPerm(Base, BaseModel):
Fixed permissions for users groups, group can have create repo permission now....
r1271 __tablename__ = 'users_group_repo_to_perm'
Nicolas VINOT
Correct code style
r1593 __table_args__ = (UniqueConstraint('repository_id', 'users_group_id', 'permission_id'), {'extend_existing':True})
fixes #288...
r1594 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
users_group_id = Column("users_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)
repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
added user group to perm table
r958
Nicolas VINOT
Correct code style
r1593 users_group = relationship('UsersGroup')
permission = relationship('Permission')
repository = relationship('Repository')
added user group to perm table
r958
Nicolas VINOT
Correct code style
r1593 def __repr__(self):
return '<userGroup:%s => %s >' % (self.users_group, self.repository)
Fixed permissions for users groups, group can have create repo permission now....
r1271
Nicolas VINOT
Correct code style
r1593 class UsersGroupToPerm(Base, BaseModel):
Fixed permissions for users groups, group can have create repo permission now....
r1271 __tablename__ = 'users_group_to_perm'
fixes #288...
r1594 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
users_group_id = Column("users_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)
Fixed permissions for users groups, group can have create repo permission now....
r1271
Nicolas VINOT
Correct code style
r1593 users_group = relationship('UsersGroup')
permission = relationship('Permission')
Fixed permissions for users groups, group can have create repo permission now....
r1271
@classmethod
Nicolas VINOT
Correct code style
r1593 def has_perm(cls, users_group_id, perm):
if not isinstance(perm, Permission):
raise Exception('perm needs to be an instance of Permission class')
Fixed permissions for users groups, group can have create repo permission now....
r1271
Nicolas VINOT
Correct code style
r1593 return cls.query().filter(cls.users_group_id ==
users_group_id)\
.filter(cls.permission == perm)\
Fixed permissions for users groups, group can have create repo permission now....
r1271 .scalar() is not None
@classmethod
Nicolas VINOT
Correct code style
r1593 def grant_perm(cls, users_group_id, perm):
if not isinstance(perm, Permission):
raise Exception('perm needs to be an instance of Permission class')
Fixed permissions for users groups, group can have create repo permission now....
r1271
new = cls()
new.users_group_id = users_group_id
new.permission = perm
try:
Nicolas VINOT
Correct code style
r1593 Session.add(new)
Fixed permissions for users groups, group can have create repo permission now....
r1271 Session.commit()
except:
Session.rollback()
@classmethod
Nicolas VINOT
Correct code style
r1593 def revoke_perm(cls, users_group_id, perm):
if not isinstance(perm, Permission):
raise Exception('perm needs to be an instance of Permission class')
Fixed permissions for users groups, group can have create repo permission now....
r1271
try:
Nicolas VINOT
Correct code style
r1593 cls.query().filter(cls.users_group_id == users_group_id)\
.filter(cls.permission == perm).delete()
Fixed permissions for users groups, group can have create repo permission now....
r1271 Session.commit()
except:
Session.rollback()
refactoring of models names for repoGroup permissions
r1633 class UserRepoGroupToPerm(Base, BaseModel):
added group to perm mapping table
r879 __tablename__ = 'group_to_perm'
Nicolas VINOT
Correct code style
r1593 __table_args__ = (UniqueConstraint('group_id', 'permission_id'), {'extend_existing':True})
added group to perm mapping table
r879
fixes #288...
r1594 group_to_perm_id = Column("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)
group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
added group to perm mapping table
r879
Nicolas VINOT
Correct code style
r1593 user = relationship('User')
permission = relationship('Permission')
refactoring of models names for repoGroup permissions
r1633 group = relationship('RepoGroup')
class UsersGroupRepoGroupToPerm(Base, BaseModel):
__tablename__ = 'users_group_repo_group_to_perm'
__table_args__ = (UniqueConstraint('group_id', 'permission_id'), {'extend_existing':True})
users_group_repo_group_to_perm_id = Column("users_group_repo_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
users_group_id = Column("users_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)
group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
users_group = relationship('UsersGroup')
permission = relationship('Permission')
group = relationship('RepoGroup')
added group to perm mapping table
r879
Nicolas VINOT
Correct code style
r1593 class Statistics(Base, BaseModel):
renamed project to rhodecode
r547 __tablename__ = 'statistics'
Nicolas VINOT
Correct code style
r1593 __table_args__ = (UniqueConstraint('repository_id'), {'extend_existing':True})
fixes #288...
r1594 stat_id = Column("stat_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=True, default=None)
stat_on_revision = Column("stat_on_revision", Integer(), nullable=False)
commit_activity = Column("commit_activity", LargeBinary(1000000), nullable=False)#JSON data
commit_activity_combined = Column("commit_activity_combined", LargeBinary(), nullable=False)#JSON data
languages = Column("languages", LargeBinary(1000000), nullable=False)#JSON data
Hacking for git support,and new faster repo scan
r631
fixes #288...
r1594 repository = relationship('Repository', single_parent=True)
renamed project to rhodecode
r547
Nicolas VINOT
Correct code style
r1593 class UserFollowing(Base, BaseModel):
implemented user dashboards, and following system.
r734 __tablename__ = 'user_followings'
Nicolas VINOT
Correct code style
r1593 __table_args__ = (UniqueConstraint('user_id', 'follows_repository_id'),
UniqueConstraint('user_id', 'follows_user_id')
, {'extend_existing':True})
implemented user dashboards, and following system.
r734
fixes #288...
r1594 user_following_id = Column("user_following_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)
follows_repo_id = Column("follows_repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=None, default=None)
follows_user_id = Column("follows_user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
follows_from = Column('follows_from', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
implemented user dashboards, and following system.
r734
fixes #288...
r1594 user = relationship('User', primaryjoin='User.user_id==UserFollowing.user_id')
implemented user dashboards, and following system.
r734
fixes #288...
r1594 follows_user = relationship('User', primaryjoin='User.user_id==UserFollowing.follows_user_id')
follows_repository = relationship('Repository', order_by='Repository.repo_name')
implemented user dashboards, and following system.
r734
#179 Added followers page
r1279
@classmethod
Nicolas VINOT
Correct code style
r1593 def get_repo_followers(cls, repo_id):
return cls.query().filter(cls.follows_repo_id == repo_id)
#179 Added followers page
r1279
Nicolas VINOT
Correct code style
r1593 class CacheInvalidation(Base, BaseModel):
Adde table for cache invalidation
r670 __tablename__ = 'cache_invalidation'
Nicolas VINOT
Correct code style
r1593 __table_args__ = (UniqueConstraint('cache_key'), {'extend_existing':True})
fixes #288...
r1594 cache_id = Column("cache_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
cache_key = Column("cache_key", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
cache_args = Column("cache_args", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
cache_active = Column("cache_active", Boolean(), nullable=True, unique=None, default=False)
Adde table for cache invalidation
r670
fixes #288...
r1594 def __init__(self, cache_key, cache_args=''):
#50 on point cache invalidation changes....
r692 self.cache_key = cache_key
self.cache_args = cache_args
self.cache_active = False
Nicolas VINOT
Correct code style
r1593 def __repr__(self):
return "<%s('%s:%s')>" % (self.__class__.__name__,
self.cache_id, self.cache_key)
added current db version into rhodecode,...
r834
Cached readme generation...
r1607 @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:
"""
return cls.query()\
.filter(CacheInvalidation.cache_key == key)\
.filter(CacheInvalidation.cache_active == False)\
.scalar()
@classmethod
def set_invalidate(cls, key):
"""
Mark this Cache key for invalidation
:param key:
"""
log.debug('marking %s for invalidation' % key)
inv_obj = Session().query(cls)\
.filter(cls.cache_key == key).scalar()
if inv_obj:
inv_obj.cache_active = False
else:
log.debug('cache key not found in invalidation db -> creating one')
inv_obj = CacheInvalidation(key)
try:
Session.add(inv_obj)
Session.commit()
except Exception:
log.error(traceback.format_exc())
Session.rollback()
@classmethod
def set_valid(cls, key):
"""
Mark this cache key as active and currently cached
:param key:
"""
inv_obj = Session().query(CacheInvalidation)\
.filter(CacheInvalidation.cache_key == key).scalar()
inv_obj.cache_active = True
Session.add(inv_obj)
Session.commit()
Added cache options to some db getters
r1665
#77 code review...
r1670 class ChangesetComment(Base, BaseModel):
__tablename__ = 'changeset_comments'
__table_args__ = ({'extend_existing':True},)
comment_id = Column('comment_id', Integer(), nullable=False, primary_key=True)
repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
code refactoring
r1675 revision = Column('revision', String(40), nullable=False)
#71 code-review...
r1677 line_no = Column('line_no', Unicode(10), nullable=True)
f_path = Column('f_path', Unicode(1000), nullable=True)
#77 code review...
r1670 user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), nullable=False)
#71 code-review...
r1677 text = Column('text', Unicode(25000), nullable=False)
modified_at = Column('modified_at', DateTime(), nullable=False, default=datetime.datetime.now)
#77 code review...
r1670
notification fixes and improvements
r1703 author = relationship('User', lazy='joined')
#77 code review...
r1670 repo = relationship('Repository')
notification fixes and improvements
r1703 @classmethod
def get_users(cls, revision):
"""
Returns user associated with this changesetComment. ie those
who actually commented
:param cls:
:param revision:
"""
return Session.query(User)\
.filter(cls.revision == revision)\
.join(ChangesetComment.author).all()
#302 - basic notification system, models+tests
r1702 class Notification(Base, BaseModel):
__tablename__ = 'notifications'
__table_args__ = ({'extend_existing':True})
notification fixes and improvements
r1703
TYPE_CHANGESET_COMMENT = 'cs_comment'
TYPE_MESSAGE = 'message'
TYPE_MENTION = 'mention'
#302 - basic notification system, models+tests
r1702 notification_id = Column('notification_id', Integer(), nullable=False, primary_key=True)
subject = Column('subject', Unicode(512), nullable=True)
body = Column('body', Unicode(50000), nullable=True)
notification fixes and improvements
r1703 created_by = Column("created_by", Integer(), ForeignKey('users.user_id'), nullable=True)
#302 - basic notification system, models+tests
r1702 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
notification fixes and improvements
r1703 type_ = Column('type', Unicode(256))
#302 - basic notification system, models+tests
r1702
notification fixes and improvements
r1703 create_by_user = relationship('User')
#302 - basic notification system, models+tests
r1702 user_notifications = relationship('UserNotification',
primaryjoin = 'Notification.notification_id==UserNotification.notification_id',
cascade = "all, delete, delete-orphan")
@property
def recipients(self):
return [x.user for x in UserNotification.query()\
.filter(UserNotification.notification == self).all()]
@classmethod
notification fixes and improvements
r1703 def create(cls, created_by, subject, body, recipients, type_=None):
if type_ is None:
type_ = Notification.TYPE_MESSAGE
#302 - basic notification system, models+tests
r1702 notification = cls()
notification fixes and improvements
r1703 notification.create_by_user = created_by
#302 - basic notification system, models+tests
r1702 notification.subject = subject
notification.body = body
notification fixes and improvements
r1703 notification.type_ = type_
#302 - basic notification system, models+tests
r1702 Session.add(notification)
for u in recipients:
u.notifications.append(notification)
Session.commit()
return notification
class UserNotification(Base, BaseModel):
__tablename__ = 'user_to_notification'
notification fixes and improvements
r1703 __table_args__ = (UniqueConstraint('user_id', 'notification_id'),
{'extend_existing':True})
#302 - basic notification system, models+tests
r1702 user_to_notification_id = Column("user_to_notification_id", Integer(), nullable=False, unique=True, primary_key=True)
user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
notification_id = Column("notification_id", Integer(), ForeignKey('notifications.notification_id'), nullable=False)
notification fixes and improvements
r1703 read = Column('read', Boolean, default=False)
#302 - basic notification system, models+tests
r1702 sent_on = Column('sent_on', DateTime(timezone=False), nullable=True, unique=None)
user = relationship('User', single_parent=True, lazy="joined")
notification = relationship('Notification',single_parent=True,
cascade="all, delete, delete-orphan")
Nicolas VINOT
Correct code style
r1593 class DbMigrateVersion(Base, BaseModel):
added current db version into rhodecode,...
r834 __tablename__ = 'db_migrate_version'
Bumped sqlalchemy version to 0.7, replaced timerproxy with new event system for sqlalchemy....
r1360 __table_args__ = {'extend_existing':True}
fixes #288...
r1594 repository_id = Column('repository_id', String(250), primary_key=True)
Nicolas VINOT
Correct code style
r1593 repository_path = Column('repository_path', Text)
version = Column('version', Integer)
fixes #288...
r1594