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