##// END OF EJS Templates
fixes #228 - added detection of assigned groups to prevent errors on sqlite
marcink -
r1435:a62af7d5 beta
parent child Browse files
Show More
@@ -1,213 +1,216 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 rhodecode.controllers.admin.users_groups
4 4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 5
6 6 Users Groups crud controller for pylons
7 7
8 8 :created_on: Jan 25, 2011
9 9 :author: marcink
10 10 :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
11 11 :license: GPLv3, see COPYING for more details.
12 12 """
13 13 # This program is free software: you can redistribute it and/or modify
14 14 # it under the terms of the GNU General Public License as published by
15 15 # the Free Software Foundation, either version 3 of the License, or
16 16 # (at your option) any later version.
17 17 #
18 18 # This program is distributed in the hope that it will be useful,
19 19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 21 # GNU General Public License for more details.
22 22 #
23 23 # You should have received a copy of the GNU General Public License
24 24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25 25
26 26 import logging
27 27 import traceback
28 28 import formencode
29 29
30 30 from formencode import htmlfill
31 31 from pylons import request, session, tmpl_context as c, url, config
32 32 from pylons.controllers.util import abort, redirect
33 33 from pylons.i18n.translation import _
34 34
35 from rhodecode.lib.exceptions import UsersGroupsAssignedException
35 36 from rhodecode.lib import helpers as h
36 37 from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator
37 38 from rhodecode.lib.base import BaseController, render
38 39
39 40 from rhodecode.model.db import User, UsersGroup, Permission, UsersGroupToPerm
40 41 from rhodecode.model.forms import UserForm, UsersGroupForm
41 42 from rhodecode.model.users_group import UsersGroupModel
42 43
43 44 log = logging.getLogger(__name__)
44 45
45 46
46 47 class UsersGroupsController(BaseController):
47 48 """REST Controller styled on the Atom Publishing Protocol"""
48 49 # To properly map this controller, ensure your config/routing.py
49 50 # file has a resource setup:
50 51 # map.resource('users_group', 'users_groups')
51 52
52 53 @LoginRequired()
53 54 @HasPermissionAllDecorator('hg.admin')
54 55 def __before__(self):
55 56 c.admin_user = session.get('admin_user')
56 57 c.admin_username = session.get('admin_username')
57 58 super(UsersGroupsController, self).__before__()
58 59 c.available_permissions = config['available_permissions']
59 60
60 61 def index(self, format='html'):
61 62 """GET /users_groups: All items in the collection"""
62 63 # url('users_groups')
63 64 c.users_groups_list = self.sa.query(UsersGroup).all()
64 65 return render('admin/users_groups/users_groups.html')
65 66
66 67 def create(self):
67 68 """POST /users_groups: Create a new item"""
68 69 # url('users_groups')
69 70 users_group_model = UsersGroupModel()
70 71 users_group_form = UsersGroupForm()()
71 72 try:
72 73 form_result = users_group_form.to_python(dict(request.POST))
73 74 users_group_model.create(form_result)
74 75 h.flash(_('created users group %s') \
75 76 % form_result['users_group_name'], category='success')
76 77 #action_logger(self.rhodecode_user, 'new_user', '', '', self.sa)
77 78 except formencode.Invalid, errors:
78 79 return htmlfill.render(
79 80 render('admin/users_groups/users_group_add.html'),
80 81 defaults=errors.value,
81 82 errors=errors.error_dict or {},
82 83 prefix_error=False,
83 84 encoding="UTF-8")
84 85 except Exception:
85 86 log.error(traceback.format_exc())
86 87 h.flash(_('error occurred during creation of users group %s') \
87 88 % request.POST.get('users_group_name'), category='error')
88 89
89 90 return redirect(url('users_groups'))
90 91
91 92 def new(self, format='html'):
92 93 """GET /users_groups/new: Form to create a new item"""
93 94 # url('new_users_group')
94 95 return render('admin/users_groups/users_group_add.html')
95 96
96 97 def update(self, id):
97 98 """PUT /users_groups/id: Update an existing item"""
98 99 # Forms posted to this method should contain a hidden field:
99 100 # <input type="hidden" name="_method" value="PUT" />
100 101 # Or using helpers:
101 102 # h.form(url('users_group', id=ID),
102 103 # method='put')
103 104 # url('users_group', id=ID)
104 105
105 106 users_group_model = UsersGroupModel()
106 107 c.users_group = users_group_model.get(id)
107 108 c.group_members = [(x.user_id, x.user.username) for x in
108 109 c.users_group.members]
109 110
110 111 c.available_members = [(x.user_id, x.username) for x in
111 112 self.sa.query(User).all()]
112 113 users_group_form = UsersGroupForm(edit=True,
113 114 old_data=c.users_group.get_dict(),
114 115 available_members=[str(x[0]) for x
115 116 in c.available_members])()
116 117
117 118 try:
118 119 form_result = users_group_form.to_python(request.POST)
119 120 users_group_model.update(id, form_result)
120 121 h.flash(_('updated users group %s') \
121 122 % form_result['users_group_name'],
122 123 category='success')
123 124 #action_logger(self.rhodecode_user, 'new_user', '', '', self.sa)
124 125 except formencode.Invalid, errors:
125 126 e = errors.error_dict or {}
126 127
127 128 perm = Permission.get_by_key('hg.create.repository')
128 129 e.update({'create_repo_perm':
129 130 UsersGroupToPerm.has_perm(id, perm)})
130 131
131 132 return htmlfill.render(
132 133 render('admin/users_groups/users_group_edit.html'),
133 134 defaults=errors.value,
134 135 errors=e,
135 136 prefix_error=False,
136 137 encoding="UTF-8")
137 138 except Exception:
138 139 log.error(traceback.format_exc())
139 140 h.flash(_('error occurred during update of users group %s') \
140 141 % request.POST.get('users_group_name'), category='error')
141 142
142 143 return redirect(url('users_groups'))
143 144
144 145 def delete(self, id):
145 146 """DELETE /users_groups/id: Delete an existing item"""
146 147 # Forms posted to this method should contain a hidden field:
147 148 # <input type="hidden" name="_method" value="DELETE" />
148 149 # Or using helpers:
149 150 # h.form(url('users_group', id=ID),
150 151 # method='delete')
151 152 # url('users_group', id=ID)
152 153 users_group_model = UsersGroupModel()
153 154 try:
154 155 users_group_model.delete(id)
155 156 h.flash(_('successfully deleted users group'), category='success')
157 except UsersGroupsAssignedException, e:
158 h.flash(e, category='error')
156 159 except Exception:
157 160 h.flash(_('An error occurred during deletion of users group'),
158 161 category='error')
159 162 return redirect(url('users_groups'))
160 163
161 164 def show(self, id, format='html'):
162 165 """GET /users_groups/id: Show a specific item"""
163 166 # url('users_group', id=ID)
164 167
165 168 def edit(self, id, format='html'):
166 169 """GET /users_groups/id/edit: Form to edit an existing item"""
167 170 # url('edit_users_group', id=ID)
168 171
169 172 c.users_group = self.sa.query(UsersGroup).get(id)
170 173 if not c.users_group:
171 174 return redirect(url('users_groups'))
172 175
173 176 c.users_group.permissions = {}
174 177 c.group_members = [(x.user_id, x.user.username) for x in
175 178 c.users_group.members]
176 179 c.available_members = [(x.user_id, x.username) for x in
177 180 self.sa.query(User).all()]
178 181 defaults = c.users_group.get_dict()
179 182 perm = Permission.get_by_key('hg.create.repository')
180 183 defaults.update({'create_repo_perm':
181 184 UsersGroupToPerm.has_perm(id, perm)})
182 185 return htmlfill.render(
183 186 render('admin/users_groups/users_group_edit.html'),
184 187 defaults=defaults,
185 188 encoding="UTF-8",
186 189 force_defaults=False
187 190 )
188 191
189 192 def update_perm(self, id):
190 193 """PUT /users_perm/id: Update an existing item"""
191 194 # url('users_group_perm', id=ID, method='put')
192 195
193 196 grant_perm = request.POST.get('create_repo_perm', False)
194 197
195 198 if grant_perm:
196 199 perm = Permission.get_by_key('hg.create.none')
197 200 UsersGroupToPerm.revoke_perm(id, perm)
198 201
199 202 perm = Permission.get_by_key('hg.create.repository')
200 203 UsersGroupToPerm.grant_perm(id, perm)
201 204 h.flash(_("Granted 'repository create' permission to user"),
202 205 category='success')
203 206
204 207 else:
205 208 perm = Permission.get_by_key('hg.create.repository')
206 209 UsersGroupToPerm.revoke_perm(id, perm)
207 210
208 211 perm = Permission.get_by_key('hg.create.none')
209 212 UsersGroupToPerm.grant_perm(id, perm)
210 213 h.flash(_("Revoked 'repository create' permission to user"),
211 214 category='success')
212 215
213 216 return redirect(url('edit_users_group', id=id))
@@ -1,47 +1,50 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 rhodecode.lib.exceptions
4 4 ~~~~~~~~~~~~~~~~~~~~~~~~
5 5
6 6 Set of custom exceptions used in RhodeCode
7 7
8 8 :created_on: Nov 17, 2010
9 9 :copyright: (c) 2010 by marcink.
10 10 :license: LICENSE_NAME, see LICENSE_FILE for more details.
11 11 """
12 12 # This program is free software: you can redistribute it and/or modify
13 13 # it under the terms of the GNU General Public License as published by
14 14 # the Free Software Foundation, either version 3 of the License, or
15 15 # (at your option) any later version.
16 16 #
17 17 # This program is distributed in the hope that it will be useful,
18 18 # but WITHOUT ANY WARRANTY; without even the implied warranty of
19 19 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 20 # GNU General Public License for more details.
21 21 #
22 22 # You should have received a copy of the GNU General Public License
23 23 # along with this program. If not, see <http://www.gnu.org/licenses/>.
24 24
25 25
26 26 class LdapUsernameError(Exception):
27 27 pass
28 28
29 29
30 30 class LdapPasswordError(Exception):
31 31 pass
32 32
33 33
34 34 class LdapConnectionError(Exception):
35 35 pass
36 36
37 37
38 38 class LdapImportError(Exception):
39 39 pass
40 40
41 41
42 42 class DefaultUserException(Exception):
43 43 pass
44 44
45 45
46 46 class UserOwnsReposException(Exception):
47 47 pass
48
49 class UsersGroupsAssignedException(Exception):
50 pass
@@ -1,799 +1,803 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 rhodecode.model.db
4 4 ~~~~~~~~~~~~~~~~~~
5 5
6 6 Database Models for RhodeCode
7 7
8 8 :created_on: Apr 08, 2010
9 9 :author: marcink
10 10 :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
11 11 :license: GPLv3, see COPYING for more details.
12 12 """
13 13 # This program is free software: you can redistribute it and/or modify
14 14 # it under the terms of the GNU General Public License as published by
15 15 # the Free Software Foundation, either version 3 of the License, or
16 16 # (at your option) any later version.
17 17 #
18 18 # This program is distributed in the hope that it will be useful,
19 19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 21 # GNU General Public License for more details.
22 22 #
23 23 # You should have received a copy of the GNU General Public License
24 24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25 25
26 26 import os
27 27 import logging
28 28 import datetime
29 29 import traceback
30 30 from datetime import date
31 31
32 32 from sqlalchemy import *
33 33 from sqlalchemy.exc import DatabaseError
34 34 from sqlalchemy.orm import relationship, backref, joinedload, class_mapper
35 35 from sqlalchemy.orm.interfaces import MapperExtension
36 36
37 37 from beaker.cache import cache_region, region_invalidate
38 38
39 39 from vcs import get_backend
40 40 from vcs.utils.helpers import get_scm
41 41 from vcs.exceptions import RepositoryError, VCSError
42 42 from vcs.utils.lazy import LazyProperty
43 43 from vcs.nodes import FileNode
44 44
45 45 from rhodecode.lib import str2bool, json, safe_str
46 46 from rhodecode.model.meta import Base, Session
47 47 from rhodecode.model.caching_query import FromCache
48 48
49 49 log = logging.getLogger(__name__)
50 50
51 51 #==============================================================================
52 52 # BASE CLASSES
53 53 #==============================================================================
54 54
55 55 class ModelSerializer(json.JSONEncoder):
56 56 """
57 57 Simple Serializer for JSON,
58 58
59 59 usage::
60 60
61 61 to make object customized for serialization implement a __json__
62 62 method that will return a dict for serialization into json
63 63
64 64 example::
65 65
66 66 class Task(object):
67 67
68 68 def __init__(self, name, value):
69 69 self.name = name
70 70 self.value = value
71 71
72 72 def __json__(self):
73 73 return dict(name=self.name,
74 74 value=self.value)
75 75
76 76 """
77 77
78 78 def default(self, obj):
79 79
80 80 if hasattr(obj, '__json__'):
81 81 return obj.__json__()
82 82 else:
83 83 return json.JSONEncoder.default(self, obj)
84 84
85 85 class BaseModel(object):
86 86 """Base Model for all classess
87 87
88 88 """
89 89
90 90 @classmethod
91 91 def _get_keys(cls):
92 92 """return column names for this model """
93 93 return class_mapper(cls).c.keys()
94 94
95 95 def get_dict(self):
96 96 """return dict with keys and values corresponding
97 97 to this model data """
98 98
99 99 d = {}
100 100 for k in self._get_keys():
101 101 d[k] = getattr(self, k)
102 102 return d
103 103
104 104 def get_appstruct(self):
105 105 """return list with keys and values tupples corresponding
106 106 to this model data """
107 107
108 108 l = []
109 109 for k in self._get_keys():
110 110 l.append((k, getattr(self, k),))
111 111 return l
112 112
113 113 def populate_obj(self, populate_dict):
114 114 """populate model with data from given populate_dict"""
115 115
116 116 for k in self._get_keys():
117 117 if k in populate_dict:
118 118 setattr(self, k, populate_dict[k])
119 119
120 120 @classmethod
121 121 def query(cls):
122 122 return Session.query(cls)
123 123
124 124 @classmethod
125 125 def get(cls, id_):
126 126 return Session.query(cls).get(id_)
127 127
128 128
129 129 class RhodeCodeSettings(Base, BaseModel):
130 130 __tablename__ = 'rhodecode_settings'
131 131 __table_args__ = (UniqueConstraint('app_settings_name'), {'extend_existing':True})
132 132 app_settings_id = Column("app_settings_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
133 133 app_settings_name = Column("app_settings_name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
134 134 app_settings_value = Column("app_settings_value", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
135 135
136 136 def __init__(self, k='', v=''):
137 137 self.app_settings_name = k
138 138 self.app_settings_value = v
139 139
140 140 def __repr__(self):
141 141 return "<%s('%s:%s')>" % (self.__class__.__name__,
142 142 self.app_settings_name, self.app_settings_value)
143 143
144 144
145 145 @classmethod
146 146 def get_by_name(cls, ldap_key):
147 147 return Session.query(cls)\
148 148 .filter(cls.app_settings_name == ldap_key).scalar()
149 149
150 150 @classmethod
151 151 def get_app_settings(cls, cache=False):
152 152
153 153 ret = Session.query(cls)
154 154
155 155 if cache:
156 156 ret = ret.options(FromCache("sql_cache_short", "get_hg_settings"))
157 157
158 158 if not ret:
159 159 raise Exception('Could not get application settings !')
160 160 settings = {}
161 161 for each in ret:
162 162 settings['rhodecode_' + each.app_settings_name] = \
163 163 each.app_settings_value
164 164
165 165 return settings
166 166
167 167 @classmethod
168 168 def get_ldap_settings(cls, cache=False):
169 169 ret = Session.query(cls)\
170 170 .filter(cls.app_settings_name.startswith('ldap_'))\
171 171 .all()
172 172 fd = {}
173 173 for row in ret:
174 174 fd.update({row.app_settings_name:row.app_settings_value})
175 175
176 176 fd.update({'ldap_active':str2bool(fd.get('ldap_active'))})
177 177
178 178 return fd
179 179
180 180
181 181 class RhodeCodeUi(Base, BaseModel):
182 182 __tablename__ = 'rhodecode_ui'
183 183 __table_args__ = {'extend_existing':True}
184 184 ui_id = Column("ui_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
185 185 ui_section = Column("ui_section", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
186 186 ui_key = Column("ui_key", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
187 187 ui_value = Column("ui_value", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
188 188 ui_active = Column("ui_active", Boolean(), nullable=True, unique=None, default=True)
189 189
190 190
191 191 @classmethod
192 192 def get_by_key(cls, key):
193 193 return Session.query(cls).filter(cls.ui_key == key)
194 194
195 195
196 196 class User(Base, BaseModel):
197 197 __tablename__ = 'users'
198 198 __table_args__ = (UniqueConstraint('username'), UniqueConstraint('email'), {'extend_existing':True})
199 199 user_id = Column("user_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
200 200 username = Column("username", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
201 201 password = Column("password", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
202 202 active = Column("active", Boolean(), nullable=True, unique=None, default=None)
203 203 admin = Column("admin", Boolean(), nullable=True, unique=None, default=False)
204 204 name = Column("name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
205 205 lastname = Column("lastname", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
206 206 email = Column("email", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
207 207 last_login = Column("last_login", DateTime(timezone=False), nullable=True, unique=None, default=None)
208 208 ldap_dn = Column("ldap_dn", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
209 209 api_key = Column("api_key", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
210 210
211 211 user_log = relationship('UserLog', cascade='all')
212 212 user_perms = relationship('UserToPerm', primaryjoin="User.user_id==UserToPerm.user_id", cascade='all')
213 213
214 214 repositories = relationship('Repository')
215 215 user_followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_user_id==User.user_id', cascade='all')
216 216 repo_to_perm = relationship('RepoToPerm', primaryjoin='RepoToPerm.user_id==User.user_id', cascade='all')
217 217
218 218 group_member = relationship('UsersGroupMember', cascade='all')
219 219
220 220 @property
221 221 def full_contact(self):
222 222 return '%s %s <%s>' % (self.name, self.lastname, self.email)
223 223
224 224 @property
225 225 def short_contact(self):
226 226 return '%s %s' % (self.name, self.lastname)
227 227
228 228 @property
229 229 def is_admin(self):
230 230 return self.admin
231 231
232 232 def __repr__(self):
233 233 try:
234 234 return "<%s('id:%s:%s')>" % (self.__class__.__name__,
235 235 self.user_id, self.username)
236 236 except:
237 237 return self.__class__.__name__
238 238
239 239 @classmethod
240 240 def by_username(cls, username, case_insensitive=False):
241 241 if case_insensitive:
242 242 return Session.query(cls).filter(cls.username.like(username)).one()
243 243 else:
244 244 return Session.query(cls).filter(cls.username == username).one()
245 245
246 246 @classmethod
247 247 def get_by_api_key(cls, api_key):
248 248 return Session.query(cls).filter(cls.api_key == api_key).one()
249 249
250 250
251 251 def update_lastlogin(self):
252 252 """Update user lastlogin"""
253 253
254 254 self.last_login = datetime.datetime.now()
255 255 Session.add(self)
256 256 Session.commit()
257 257 log.debug('updated user %s lastlogin', self.username)
258 258
259 259
260 260 class UserLog(Base, BaseModel):
261 261 __tablename__ = 'user_logs'
262 262 __table_args__ = {'extend_existing':True}
263 263 user_log_id = Column("user_log_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
264 264 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
265 265 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
266 266 repository_name = Column("repository_name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
267 267 user_ip = Column("user_ip", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
268 268 action = Column("action", UnicodeText(length=1200000, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
269 269 action_date = Column("action_date", DateTime(timezone=False), nullable=True, unique=None, default=None)
270 270
271 271 @property
272 272 def action_as_day(self):
273 273 return date(*self.action_date.timetuple()[:3])
274 274
275 275 user = relationship('User')
276 276 repository = relationship('Repository')
277 277
278 278
279 279 class UsersGroup(Base, BaseModel):
280 280 __tablename__ = 'users_groups'
281 281 __table_args__ = {'extend_existing':True}
282 282
283 283 users_group_id = Column("users_group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
284 284 users_group_name = Column("users_group_name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None)
285 285 users_group_active = Column("users_group_active", Boolean(), nullable=True, unique=None, default=None)
286 286
287 287 members = relationship('UsersGroupMember', cascade="all, delete, delete-orphan", lazy="joined")
288 288
289 def __repr__(self):
290 return '<userGroup(%s)>' % (self.users_group_name)
289 291
290 292 @classmethod
291 293 def get_by_group_name(cls, group_name, cache=False, case_insensitive=False):
292 294 if case_insensitive:
293 295 gr = Session.query(cls)\
294 296 .filter(cls.users_group_name.ilike(group_name))
295 297 else:
296 298 gr = Session.query(UsersGroup)\
297 299 .filter(UsersGroup.users_group_name == group_name)
298 300 if cache:
299 301 gr = gr.options(FromCache("sql_cache_short",
300 302 "get_user_%s" % group_name))
301 303 return gr.scalar()
302 304
303 305 class UsersGroupMember(Base, BaseModel):
304 306 __tablename__ = 'users_groups_members'
305 307 __table_args__ = {'extend_existing':True}
306 308
307 309 users_group_member_id = Column("users_group_member_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
308 310 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
309 311 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
310 312
311 313 user = relationship('User', lazy='joined')
312 314 users_group = relationship('UsersGroup')
313 315
314 316 def __init__(self, gr_id='', u_id=''):
315 317 self.users_group_id = gr_id
316 318 self.user_id = u_id
317 319
318 320 class Repository(Base, BaseModel):
319 321 __tablename__ = 'repositories'
320 322 __table_args__ = (UniqueConstraint('repo_name'), {'extend_existing':True},)
321 323
322 324 repo_id = Column("repo_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
323 325 repo_name = Column("repo_name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None)
324 326 clone_uri = Column("clone_uri", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=False, default=None)
325 327 repo_type = Column("repo_type", String(length=255, convert_unicode=False, assert_unicode=None), nullable=False, unique=False, default='hg')
326 328 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
327 329 private = Column("private", Boolean(), nullable=True, unique=None, default=None)
328 330 enable_statistics = Column("statistics", Boolean(), nullable=True, unique=None, default=True)
329 331 enable_downloads = Column("downloads", Boolean(), nullable=True, unique=None, default=True)
330 332 description = Column("description", String(length=10000, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
331 333 created_on = Column('created_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
332 334
333 335 fork_id = Column("fork_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=False, default=None)
334 336 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=False, default=None)
335 337
336 338
337 339 user = relationship('User')
338 340 fork = relationship('Repository', remote_side=repo_id)
339 341 group = relationship('Group')
340 342 repo_to_perm = relationship('RepoToPerm', cascade='all', order_by='RepoToPerm.repo_to_perm_id')
341 343 users_group_to_perm = relationship('UsersGroupRepoToPerm', cascade='all')
342 344 stats = relationship('Statistics', cascade='all', uselist=False)
343 345
344 346 followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_repo_id==Repository.repo_id', cascade='all')
345 347
346 348 logs = relationship('UserLog', cascade='all')
347 349
348 350 def __repr__(self):
349 351 return "<%s('%s:%s')>" % (self.__class__.__name__,
350 352 self.repo_id, self.repo_name)
351 353
352 354 @classmethod
353 355 def by_repo_name(cls, repo_name):
354 356 q = Session.query(cls).filter(cls.repo_name == repo_name)
355 357
356 358 q = q.options(joinedload(Repository.fork))\
357 359 .options(joinedload(Repository.user))\
358 360 .options(joinedload(Repository.group))\
359 361
360 362 return q.one()
361 363
362 364 @classmethod
363 365 def get_repo_forks(cls, repo_id):
364 366 return Session.query(cls).filter(Repository.fork_id == repo_id)
365 367
366 368 @property
367 369 def just_name(self):
368 370 return self.repo_name.split(os.sep)[-1]
369 371
370 372 @property
371 373 def groups_with_parents(self):
372 374 groups = []
373 375 if self.group is None:
374 376 return groups
375 377
376 378 cur_gr = self.group
377 379 groups.insert(0, cur_gr)
378 380 while 1:
379 381 gr = getattr(cur_gr, 'parent_group', None)
380 382 cur_gr = cur_gr.parent_group
381 383 if gr is None:
382 384 break
383 385 groups.insert(0, gr)
384 386
385 387 return groups
386 388
387 389 @property
388 390 def groups_and_repo(self):
389 391 return self.groups_with_parents, self.just_name
390 392
391 393 @LazyProperty
392 394 def repo_path(self):
393 395 """
394 396 Returns base full path for that repository means where it actually
395 397 exists on a filesystem
396 398 """
397 399 q = Session.query(RhodeCodeUi).filter(RhodeCodeUi.ui_key == '/')
398 400 q.options(FromCache("sql_cache_short", "repository_repo_path"))
399 401 return q.one().ui_value
400 402
401 403 @property
402 404 def repo_full_path(self):
403 405 p = [self.repo_path]
404 406 # we need to split the name by / since this is how we store the
405 407 # names in the database, but that eventually needs to be converted
406 408 # into a valid system path
407 409 p += self.repo_name.split('/')
408 410 return os.path.join(*p)
409 411
410 412 @property
411 413 def _ui(self):
412 414 """
413 415 Creates an db based ui object for this repository
414 416 """
415 417 from mercurial import ui
416 418 from mercurial import config
417 419 baseui = ui.ui()
418 420
419 421 #clean the baseui object
420 422 baseui._ocfg = config.config()
421 423 baseui._ucfg = config.config()
422 424 baseui._tcfg = config.config()
423 425
424 426
425 427 ret = Session.query(RhodeCodeUi)\
426 428 .options(FromCache("sql_cache_short",
427 429 "repository_repo_ui")).all()
428 430
429 431 hg_ui = ret
430 432 for ui_ in hg_ui:
431 433 if ui_.ui_active:
432 434 log.debug('settings ui from db[%s]%s:%s', ui_.ui_section,
433 435 ui_.ui_key, ui_.ui_value)
434 436 baseui.setconfig(ui_.ui_section, ui_.ui_key, ui_.ui_value)
435 437
436 438 return baseui
437 439
438 440 #==========================================================================
439 441 # SCM CACHE INSTANCE
440 442 #==========================================================================
441 443
442 444 @property
443 445 def invalidate(self):
444 446 """
445 447 Returns Invalidation object if this repo should be invalidated
446 448 None otherwise. `cache_active = False` means that this cache
447 449 state is not valid and needs to be invalidated
448 450 """
449 451 return Session.query(CacheInvalidation)\
450 452 .filter(CacheInvalidation.cache_key == self.repo_name)\
451 453 .filter(CacheInvalidation.cache_active == False)\
452 454 .scalar()
453 455
454 456 def set_invalidate(self):
455 457 """
456 458 set a cache for invalidation for this instance
457 459 """
458 460 inv = Session.query(CacheInvalidation)\
459 461 .filter(CacheInvalidation.cache_key == self.repo_name)\
460 462 .scalar()
461 463
462 464 if inv is None:
463 465 inv = CacheInvalidation(self.repo_name)
464 466 inv.cache_active = True
465 467 Session.add(inv)
466 468 Session.commit()
467 469
468 470 @property
469 471 def scm_instance(self):
470 472 return self.__get_instance()
471 473
472 474 @property
473 475 def scm_instance_cached(self):
474 476 @cache_region('long_term')
475 477 def _c(repo_name):
476 478 return self.__get_instance()
477 479
478 480 # TODO: remove this trick when beaker 1.6 is released
479 481 # and have fixed this issue with not supporting unicode keys
480 482 rn = safe_str(self.repo_name)
481 483
482 484 inv = self.invalidate
483 485 if inv is not None:
484 486 region_invalidate(_c, None, rn)
485 487 # update our cache
486 488 inv.cache_active = True
487 489 Session.add(inv)
488 490 Session.commit()
489 491
490 492 return _c(rn)
491 493
492 494 def __get_instance(self):
493 495
494 496 repo_full_path = self.repo_full_path
495 497
496 498 try:
497 499 alias = get_scm(repo_full_path)[0]
498 500 log.debug('Creating instance of %s repository', alias)
499 501 backend = get_backend(alias)
500 502 except VCSError:
501 503 log.error(traceback.format_exc())
502 504 log.error('Perhaps this repository is in db and not in '
503 505 'filesystem run rescan repositories with '
504 506 '"destroy old data " option from admin panel')
505 507 return
506 508
507 509 if alias == 'hg':
508 510
509 511 repo = backend(safe_str(repo_full_path), create=False,
510 512 baseui=self._ui)
511 513 #skip hidden web repository
512 514 if repo._get_hidden():
513 515 return
514 516 else:
515 517 repo = backend(repo_full_path, create=False)
516 518
517 519 return repo
518 520
519 521
520 522 class Group(Base, BaseModel):
521 523 __tablename__ = 'groups'
522 524 __table_args__ = (UniqueConstraint('group_name', 'group_parent_id'),
523 525 CheckConstraint('group_id != group_parent_id'), {'extend_existing':True},)
524 526 __mapper_args__ = {'order_by':'group_name'}
525 527
526 528 group_id = Column("group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
527 529 group_name = Column("group_name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None)
528 530 group_parent_id = Column("group_parent_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=None, default=None)
529 531 group_description = Column("group_description", String(length=10000, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
530 532
531 533 parent_group = relationship('Group', remote_side=group_id)
532 534
533 535
534 536 def __init__(self, group_name='', parent_group=None):
535 537 self.group_name = group_name
536 538 self.parent_group = parent_group
537 539
538 540 def __repr__(self):
539 541 return "<%s('%s:%s')>" % (self.__class__.__name__, self.group_id,
540 542 self.group_name)
541 543
542 544 @classmethod
543 545 def url_sep(cls):
544 546 return '/'
545 547
546 548 @property
547 549 def parents(self):
548 550 parents_recursion_limit = 5
549 551 groups = []
550 552 if self.parent_group is None:
551 553 return groups
552 554 cur_gr = self.parent_group
553 555 groups.insert(0, cur_gr)
554 556 cnt = 0
555 557 while 1:
556 558 cnt += 1
557 559 gr = getattr(cur_gr, 'parent_group', None)
558 560 cur_gr = cur_gr.parent_group
559 561 if gr is None:
560 562 break
561 563 if cnt == parents_recursion_limit:
562 564 # this will prevent accidental infinit loops
563 565 log.error('group nested more than %s' %
564 566 parents_recursion_limit)
565 567 break
566 568
567 569 groups.insert(0, gr)
568 570 return groups
569 571
570 572 @property
571 573 def children(self):
572 574 return Session.query(Group).filter(Group.parent_group == self)
573 575
574 576 @property
575 577 def full_path(self):
576 578 return Group.url_sep().join([g.group_name for g in self.parents] +
577 579 [self.group_name])
578 580
579 581 @property
580 582 def repositories(self):
581 583 return Session.query(Repository).filter(Repository.group == self)
582 584
583 585 @property
584 586 def repositories_recursive_count(self):
585 587 cnt = self.repositories.count()
586 588
587 589 def children_count(group):
588 590 cnt = 0
589 591 for child in group.children:
590 592 cnt += child.repositories.count()
591 593 cnt += children_count(child)
592 594 return cnt
593 595
594 596 return cnt + children_count(self)
595 597
596 598 class Permission(Base, BaseModel):
597 599 __tablename__ = 'permissions'
598 600 __table_args__ = {'extend_existing':True}
599 601 permission_id = Column("permission_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
600 602 permission_name = Column("permission_name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
601 603 permission_longname = Column("permission_longname", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
602 604
603 605 def __repr__(self):
604 606 return "<%s('%s:%s')>" % (self.__class__.__name__,
605 607 self.permission_id, self.permission_name)
606 608
607 609 @classmethod
608 610 def get_by_key(cls, key):
609 611 return Session.query(cls).filter(cls.permission_name == key).scalar()
610 612
611 613 class RepoToPerm(Base, BaseModel):
612 614 __tablename__ = 'repo_to_perm'
613 615 __table_args__ = (UniqueConstraint('user_id', 'repository_id'), {'extend_existing':True})
614 616 repo_to_perm_id = Column("repo_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
615 617 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
616 618 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
617 619 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
618 620
619 621 user = relationship('User')
620 622 permission = relationship('Permission')
621 623 repository = relationship('Repository')
622 624
623 625 class UserToPerm(Base, BaseModel):
624 626 __tablename__ = 'user_to_perm'
625 627 __table_args__ = (UniqueConstraint('user_id', 'permission_id'), {'extend_existing':True})
626 628 user_to_perm_id = Column("user_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
627 629 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
628 630 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
629 631
630 632 user = relationship('User')
631 633 permission = relationship('Permission')
632 634
633 635 @classmethod
634 636 def has_perm(cls, user_id, perm):
635 637 if not isinstance(perm, Permission):
636 638 raise Exception('perm needs to be an instance of Permission class')
637 639
638 640 return Session.query(cls).filter(cls.user_id == user_id)\
639 641 .filter(cls.permission == perm).scalar() is not None
640 642
641 643 @classmethod
642 644 def grant_perm(cls, user_id, perm):
643 645 if not isinstance(perm, Permission):
644 646 raise Exception('perm needs to be an instance of Permission class')
645 647
646 648 new = cls()
647 649 new.user_id = user_id
648 650 new.permission = perm
649 651 try:
650 652 Session.add(new)
651 653 Session.commit()
652 654 except:
653 655 Session.rollback()
654 656
655 657
656 658 @classmethod
657 659 def revoke_perm(cls, user_id, perm):
658 660 if not isinstance(perm, Permission):
659 661 raise Exception('perm needs to be an instance of Permission class')
660 662
661 663 try:
662 664 Session.query(cls).filter(cls.user_id == user_id)\
663 665 .filter(cls.permission == perm).delete()
664 666 Session.commit()
665 667 except:
666 668 Session.rollback()
667 669
668 670 class UsersGroupRepoToPerm(Base, BaseModel):
669 671 __tablename__ = 'users_group_repo_to_perm'
670 672 __table_args__ = (UniqueConstraint('repository_id', 'users_group_id', 'permission_id'), {'extend_existing':True})
671 673 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
672 674 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
673 675 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
674 676 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
675 677
676 678 users_group = relationship('UsersGroup')
677 679 permission = relationship('Permission')
678 680 repository = relationship('Repository')
679 681
682 def __repr__(self):
683 return '<userGroup:%s => %s >' % (self.users_group, self.repository)
680 684
681 685 class UsersGroupToPerm(Base, BaseModel):
682 686 __tablename__ = 'users_group_to_perm'
683 687 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
684 688 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
685 689 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
686 690
687 691 users_group = relationship('UsersGroup')
688 692 permission = relationship('Permission')
689 693
690 694
691 695 @classmethod
692 696 def has_perm(cls, users_group_id, perm):
693 697 if not isinstance(perm, Permission):
694 698 raise Exception('perm needs to be an instance of Permission class')
695 699
696 700 return Session.query(cls).filter(cls.users_group_id ==
697 701 users_group_id)\
698 702 .filter(cls.permission == perm)\
699 703 .scalar() is not None
700 704
701 705 @classmethod
702 706 def grant_perm(cls, users_group_id, perm):
703 707 if not isinstance(perm, Permission):
704 708 raise Exception('perm needs to be an instance of Permission class')
705 709
706 710 new = cls()
707 711 new.users_group_id = users_group_id
708 712 new.permission = perm
709 713 try:
710 714 Session.add(new)
711 715 Session.commit()
712 716 except:
713 717 Session.rollback()
714 718
715 719
716 720 @classmethod
717 721 def revoke_perm(cls, users_group_id, perm):
718 722 if not isinstance(perm, Permission):
719 723 raise Exception('perm needs to be an instance of Permission class')
720 724
721 725 try:
722 726 Session.query(cls).filter(cls.users_group_id == users_group_id)\
723 727 .filter(cls.permission == perm).delete()
724 728 Session.commit()
725 729 except:
726 730 Session.rollback()
727 731
728 732
729 733 class GroupToPerm(Base, BaseModel):
730 734 __tablename__ = 'group_to_perm'
731 735 __table_args__ = (UniqueConstraint('group_id', 'permission_id'), {'extend_existing':True})
732 736
733 737 group_to_perm_id = Column("group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
734 738 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
735 739 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
736 740 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
737 741
738 742 user = relationship('User')
739 743 permission = relationship('Permission')
740 744 group = relationship('Group')
741 745
742 746 class Statistics(Base, BaseModel):
743 747 __tablename__ = 'statistics'
744 748 __table_args__ = (UniqueConstraint('repository_id'), {'extend_existing':True})
745 749 stat_id = Column("stat_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
746 750 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=True, default=None)
747 751 stat_on_revision = Column("stat_on_revision", Integer(), nullable=False)
748 752 commit_activity = Column("commit_activity", LargeBinary(1000000), nullable=False)#JSON data
749 753 commit_activity_combined = Column("commit_activity_combined", LargeBinary(), nullable=False)#JSON data
750 754 languages = Column("languages", LargeBinary(1000000), nullable=False)#JSON data
751 755
752 756 repository = relationship('Repository', single_parent=True)
753 757
754 758 class UserFollowing(Base, BaseModel):
755 759 __tablename__ = 'user_followings'
756 760 __table_args__ = (UniqueConstraint('user_id', 'follows_repository_id'),
757 761 UniqueConstraint('user_id', 'follows_user_id')
758 762 , {'extend_existing':True})
759 763
760 764 user_following_id = Column("user_following_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
761 765 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
762 766 follows_repo_id = Column("follows_repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=None, default=None)
763 767 follows_user_id = Column("follows_user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
764 768 follows_from = Column('follows_from', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
765 769
766 770 user = relationship('User', primaryjoin='User.user_id==UserFollowing.user_id')
767 771
768 772 follows_user = relationship('User', primaryjoin='User.user_id==UserFollowing.follows_user_id')
769 773 follows_repository = relationship('Repository', order_by='Repository.repo_name')
770 774
771 775
772 776 @classmethod
773 777 def get_repo_followers(cls, repo_id):
774 778 return Session.query(cls).filter(cls.follows_repo_id == repo_id)
775 779
776 780 class CacheInvalidation(Base, BaseModel):
777 781 __tablename__ = 'cache_invalidation'
778 782 __table_args__ = (UniqueConstraint('cache_key'), {'extend_existing':True})
779 783 cache_id = Column("cache_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
780 784 cache_key = Column("cache_key", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
781 785 cache_args = Column("cache_args", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
782 786 cache_active = Column("cache_active", Boolean(), nullable=True, unique=None, default=False)
783 787
784 788
785 789 def __init__(self, cache_key, cache_args=''):
786 790 self.cache_key = cache_key
787 791 self.cache_args = cache_args
788 792 self.cache_active = False
789 793
790 794 def __repr__(self):
791 795 return "<%s('%s:%s')>" % (self.__class__.__name__,
792 796 self.cache_id, self.cache_key)
793 797
794 798 class DbMigrateVersion(Base, BaseModel):
795 799 __tablename__ = 'db_migrate_version'
796 800 __table_args__ = {'extend_existing':True}
797 801 repository_id = Column('repository_id', String(250), primary_key=True)
798 802 repository_path = Column('repository_path', Text)
799 803 version = Column('version', Integer)
@@ -1,93 +1,105 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 rhodecode.model.user_group
4 4 ~~~~~~~~~~~~~~~~~~~~~~~~~~
5 5
6 6 users groups model for RhodeCode
7 7
8 8 :created_on: Jan 25, 2011
9 9 :author: marcink
10 10 :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
11 11 :license: GPLv3, see COPYING for more details.
12 12 """
13 13 # This program is free software: you can redistribute it and/or modify
14 14 # it under the terms of the GNU General Public License as published by
15 15 # the Free Software Foundation, either version 3 of the License, or
16 16 # (at your option) any later version.
17 17 #
18 18 # This program is distributed in the hope that it will be useful,
19 19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 21 # GNU General Public License for more details.
22 22 #
23 23 # You should have received a copy of the GNU General Public License
24 24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25 25
26 26 import logging
27 27 import traceback
28 28
29 29 from pylons.i18n.translation import _
30 30
31 from rhodecode.lib.exceptions import UsersGroupsAssignedException
31 32 from rhodecode.model import BaseModel
32 33 from rhodecode.model.caching_query import FromCache
33 from rhodecode.model.db import UsersGroup, UsersGroupMember
34 from rhodecode.model.db import UsersGroup, UsersGroupMember, \
35 UsersGroupRepoToPerm
34 36
35 37 log = logging.getLogger(__name__)
36 38
37 39
38 40 class UsersGroupModel(BaseModel):
39 41
40 42 def get(self, users_group_id, cache=False):
41 43 users_group = self.sa.query(UsersGroup)
42 44 if cache:
43 45 users_group = users_group.options(FromCache("sql_cache_short",
44 46 "get_users_group_%s" % users_group_id))
45 47 return users_group.get(users_group_id)
46 48
47 49 def create(self, form_data):
48 50 try:
49 51 new_users_group = UsersGroup()
50 52 for k, v in form_data.items():
51 53 setattr(new_users_group, k, v)
52 54
53 55 self.sa.add(new_users_group)
54 56 self.sa.commit()
55 57 except:
56 58 log.error(traceback.format_exc())
57 59 self.sa.rollback()
58 60 raise
59 61
60 62 def update(self, users_group_id, form_data):
61 63
62 64 try:
63 65 users_group = self.get(users_group_id, cache=False)
64 66
65 67 for k, v in form_data.items():
66 68 if k == 'users_group_members':
67 69 users_group.members = []
68 70 self.sa.flush()
69 71 members_list = []
70 72 if v:
71 73 for u_id in set(v):
72 74 members_list.append(UsersGroupMember(
73 75 users_group_id,
74 76 u_id))
75 77 setattr(users_group, 'members', members_list)
76 78 setattr(users_group, k, v)
77 79
78 80 self.sa.add(users_group)
79 81 self.sa.commit()
80 82 except:
81 83 log.error(traceback.format_exc())
82 84 self.sa.rollback()
83 85 raise
84 86
85 87 def delete(self, users_group_id):
86 88 try:
89
90 # check if this group is not assigned to repo
91 assigned_groups = UsersGroupRepoToPerm.query()\
92 .filter(UsersGroupRepoToPerm.users_group_id ==
93 users_group_id).all()
94
95 if assigned_groups:
96 raise UsersGroupsAssignedException('Group assigned to %s' %
97 assigned_groups)
98
87 99 users_group = self.get(users_group_id, cache=False)
88 100 self.sa.delete(users_group)
89 101 self.sa.commit()
90 102 except:
91 103 log.error(traceback.format_exc())
92 104 self.sa.rollback()
93 105 raise
General Comments 0
You need to be logged in to leave comments. Login now