##// END OF EJS Templates
Merge
leonardo -
r3530:53eafc98 merge beta
parent child Browse files
Show More
@@ -33,3 +33,4 b' List of contributors to RhodeCode projec'
33 Philip Jameson <philip.j@hostdime.com>
33 Philip Jameson <philip.j@hostdime.com>
34 Mads Kiilerich <madski@unity3d.com>
34 Mads Kiilerich <madski@unity3d.com>
35 Dan Sheridan <djs@adelard.com>
35 Dan Sheridan <djs@adelard.com>
36 Dennis Brakhane <brakhane@googlemail.com>
@@ -75,7 +75,7 b' RhodeCode Features'
75 - Supports http/https, LDAP, AD, proxy-pass authentication.
75 - Supports http/https, LDAP, AD, proxy-pass authentication.
76 - Full permissions (private/read/write/admin) together with IP restrictions for each repository,
76 - Full permissions (private/read/write/admin) together with IP restrictions for each repository,
77 additional explicit forking and repository creation permissions.
77 additional explicit forking and repository creation permissions.
78 - Users groups for easier permission management
78 - User groups for easier permission management
79 - Repository groups let you group repos and manage them easier.
79 - Repository groups let you group repos and manage them easier.
80 - Users can fork other users repos, and compare them at any time.
80 - Users can fork other users repos, and compare them at any time.
81 - Integrates easily with other systems, with custom created mappers you can connect it to almost
81 - Integrates easily with other systems, with custom created mappers you can connect it to almost
@@ -436,7 +436,7 b' OUTPUT::'
436 get_users_group
436 get_users_group
437 ---------------
437 ---------------
438
438
439 Gets an existing users group. This command can be executed only using api_key
439 Gets an existing user group. This command can be executed only using api_key
440 belonging to user with admin rights.
440 belonging to user with admin rights.
441
441
442
442
@@ -446,7 +446,7 b' INPUT::'
446 api_key : "<api_key>"
446 api_key : "<api_key>"
447 method : "get_users_group"
447 method : "get_users_group"
448 args : {
448 args : {
449 "usersgroupid" : "<users group id or name>"
449 "usersgroupid" : "<user group id or name>"
450 }
450 }
451
451
452 OUTPUT::
452 OUTPUT::
@@ -479,7 +479,7 b' OUTPUT::'
479 get_users_groups
479 get_users_groups
480 ----------------
480 ----------------
481
481
482 Lists all existing users groups. This command can be executed only using
482 Lists all existing user groups. This command can be executed only using
483 api_key belonging to user with admin rights.
483 api_key belonging to user with admin rights.
484
484
485
485
@@ -507,7 +507,7 b' OUTPUT::'
507 create_users_group
507 create_users_group
508 ------------------
508 ------------------
509
509
510 Creates new users group. This command can be executed only using api_key
510 Creates new user group. This command can be executed only using api_key
511 belonging to user with admin rights
511 belonging to user with admin rights
512
512
513
513
@@ -525,7 +525,7 b' OUTPUT::'
525
525
526 id : <id_given_in_input>
526 id : <id_given_in_input>
527 result: {
527 result: {
528 "msg": "created new users group `<groupname>`",
528 "msg": "created new user group `<groupname>`",
529 "users_group": {
529 "users_group": {
530 "users_group_id" : "<id>",
530 "users_group_id" : "<id>",
531 "group_name" : "<groupname>",
531 "group_name" : "<groupname>",
@@ -538,7 +538,7 b' OUTPUT::'
538 add_user_to_users_group
538 add_user_to_users_group
539 -----------------------
539 -----------------------
540
540
541 Adds a user to a users group. If user exists in that group success will be
541 Adds a user to a user group. If user exists in that group success will be
542 `false`. This command can be executed only using api_key
542 `false`. This command can be executed only using api_key
543 belonging to user with admin rights
543 belonging to user with admin rights
544
544
@@ -549,7 +549,7 b' INPUT::'
549 api_key : "<api_key>"
549 api_key : "<api_key>"
550 method : "add_user_users_group"
550 method : "add_user_users_group"
551 args: {
551 args: {
552 "usersgroupid" : "<users group id or name>",
552 "usersgroupid" : "<user group id or name>",
553 "userid" : "<user_id or username>",
553 "userid" : "<user_id or username>",
554 }
554 }
555
555
@@ -558,7 +558,7 b' OUTPUT::'
558 id : <id_given_in_input>
558 id : <id_given_in_input>
559 result: {
559 result: {
560 "success": True|False # depends on if member is in group
560 "success": True|False # depends on if member is in group
561 "msg": "added member `<username>` to users group `<groupname>` |
561 "msg": "added member `<username>` to user group `<groupname>` |
562 User is already in that group"
562 User is already in that group"
563 }
563 }
564 error: null
564 error: null
@@ -567,7 +567,7 b' OUTPUT::'
567 remove_user_from_users_group
567 remove_user_from_users_group
568 ----------------------------
568 ----------------------------
569
569
570 Removes a user from a users group. If user is not in given group success will
570 Removes a user from a user group. If user is not in given group success will
571 be `false`. This command can be executed only
571 be `false`. This command can be executed only
572 using api_key belonging to user with admin rights
572 using api_key belonging to user with admin rights
573
573
@@ -578,7 +578,7 b' INPUT::'
578 api_key : "<api_key>"
578 api_key : "<api_key>"
579 method : "remove_user_from_users_group"
579 method : "remove_user_from_users_group"
580 args: {
580 args: {
581 "usersgroupid" : "<users group id or name>",
581 "usersgroupid" : "<user group id or name>",
582 "userid" : "<user_id or username>",
582 "userid" : "<user_id or username>",
583 }
583 }
584
584
@@ -587,7 +587,7 b' OUTPUT::'
587 id : <id_given_in_input>
587 id : <id_given_in_input>
588 result: {
588 result: {
589 "success": True|False, # depends on if member is in group
589 "success": True|False, # depends on if member is in group
590 "msg": "removed member <username> from users group <groupname> |
590 "msg": "removed member <username> from user group <groupname> |
591 User wasn't in group"
591 User wasn't in group"
592 }
592 }
593 error: null
593 error: null
@@ -929,7 +929,7 b' OUTPUT::'
929 grant_users_group_permission
929 grant_users_group_permission
930 ----------------------------
930 ----------------------------
931
931
932 Grant permission for users group on given repository, or update
932 Grant permission for user group on given repository, or update
933 existing one if found. This command can be executed only using
933 existing one if found. This command can be executed only using
934 api_key belonging to user with admin rights.
934 api_key belonging to user with admin rights.
935
935
@@ -941,7 +941,7 b' INPUT::'
941 method : "grant_users_group_permission"
941 method : "grant_users_group_permission"
942 args: {
942 args: {
943 "repoid" : "<reponame or repo_id>"
943 "repoid" : "<reponame or repo_id>"
944 "usersgroupid" : "<users group id or name>"
944 "usersgroupid" : "<user group id or name>"
945 "perm" : "(repository.(none|read|write|admin))",
945 "perm" : "(repository.(none|read|write|admin))",
946 }
946 }
947
947
@@ -958,7 +958,7 b' OUTPUT::'
958 revoke_users_group_permission
958 revoke_users_group_permission
959 -----------------------------
959 -----------------------------
960
960
961 Revoke permission for users group on given repository.This command can be
961 Revoke permission for user group on given repository.This command can be
962 executed only using api_key belonging to user with admin rights.
962 executed only using api_key belonging to user with admin rights.
963
963
964 INPUT::
964 INPUT::
@@ -968,7 +968,7 b' INPUT::'
968 method : "revoke_users_group_permission"
968 method : "revoke_users_group_permission"
969 args: {
969 args: {
970 "repoid" : "<reponame or repo_id>"
970 "repoid" : "<reponame or repo_id>"
971 "usersgroupid" : "<users group id or name>"
971 "usersgroupid" : "<user group id or name>"
972 }
972 }
973
973
974 OUTPUT::
974 OUTPUT::
@@ -196,7 +196,7 b' news'
196 fixes
196 fixes
197 +++++
197 +++++
198
198
199 - fixed #570 explicit users group permissions can overwrite owner permissions
199 - fixed #570 explicit user group permissions can overwrite owner permissions
200 - fixed #578 set proper PATH with current Python for Git
200 - fixed #578 set proper PATH with current Python for Git
201 hooks to execute within same Python as RhodeCode
201 hooks to execute within same Python as RhodeCode
202 - fixed issue with Git bare repos that ends with .git in name
202 - fixed issue with Git bare repos that ends with .git in name
@@ -385,7 +385,7 b' news'
385 - created rcextensions module with additional mappings (ref #322) and
385 - created rcextensions module with additional mappings (ref #322) and
386 post push/pull/create repo hooks callbacks
386 post push/pull/create repo hooks callbacks
387 - implemented #377 Users view for his own permissions on account page
387 - implemented #377 Users view for his own permissions on account page
388 - #399 added inheritance of permissions for users group on repos groups
388 - #399 added inheritance of permissions for user group on repos groups
389 - #401 repository group is automatically pre-selected when adding repos
389 - #401 repository group is automatically pre-selected when adding repos
390 inside a repository group
390 inside a repository group
391 - added alternative HTTP 403 response when client failed to authenticate. Helps
391 - added alternative HTTP 403 response when client failed to authenticate. Helps
@@ -520,7 +520,7 b' fixes'
520 and groups
520 and groups
521 - fixes #271 rare JSON serialization problem with statistics
521 - fixes #271 rare JSON serialization problem with statistics
522 - fixes #337 missing validation check for conflicting names of a group with a
522 - fixes #337 missing validation check for conflicting names of a group with a
523 repositories group
523 repository group
524 - #340 fixed session problem for mysql and celery tasks
524 - #340 fixed session problem for mysql and celery tasks
525 - fixed #331 RhodeCode mangles repository names if the a repository group
525 - fixed #331 RhodeCode mangles repository names if the a repository group
526 contains the "full path" to the repositories
526 contains the "full path" to the repositories
@@ -654,7 +654,7 b' news'
654 - implemented #93 customizable changelog on combined revision ranges -
654 - implemented #93 customizable changelog on combined revision ranges -
655 equivalent of githubs compare view
655 equivalent of githubs compare view
656 - implemented #108 extended and more powerful LDAP configuration
656 - implemented #108 extended and more powerful LDAP configuration
657 - implemented #56 users groups
657 - implemented #56 user groups
658 - major code rewrites optimized codes for speed and memory usage
658 - major code rewrites optimized codes for speed and memory usage
659 - raw and diff downloads are now in git format
659 - raw and diff downloads are now in git format
660 - setup command checks for write access to given path
660 - setup command checks for write access to given path
@@ -47,7 +47,7 b' choose "Visual C++ 2008 Express" when in'
47 required, you can uncheck them
47 required, you can uncheck them
48
48
49 .. note::
49 .. note::
50
50
51 64bit: You also need to install the Microsoft Windows SDK for .NET 3.5 SP1 (.NET 4.0 won't work).
51 64bit: You also need to install the Microsoft Windows SDK for .NET 3.5 SP1 (.NET 4.0 won't work).
52 Download from: http://www.microsoft.com/en-us/download/details.aspx?id=3138
52 Download from: http://www.microsoft.com/en-us/download/details.aspx?id=3138
53
53
@@ -90,7 +90,7 b' http://sourceforge.net/projects/pywin32/'
90 .. note::
90 .. note::
91
91
92 64bit: Download and install the 64bit version.
92 64bit: Download and install the 64bit version.
93 At the time of writing you can find this at:
93 At the time of writing you can find this at:
94 http://sourceforge.net/projects/pywin32/files/pywin32/Build%20218/pywin32-218.win-amd64-py2.7.exe/download
94 http://sourceforge.net/projects/pywin32/files/pywin32/Build%20218/pywin32-218.win-amd64-py2.7.exe/download
95
95
96 Step4 - Python BIN
96 Step4 - Python BIN
@@ -51,4 +51,4 b''
51 .vc { color: #ff99ff } /* Name.Variable.Class */
51 .vc { color: #ff99ff } /* Name.Variable.Class */
52 .vg { color: #ff99ff } /* Name.Variable.Global */
52 .vg { color: #ff99ff } /* Name.Variable.Global */
53 .vi { color: #ff99ff } /* Name.Variable.Instance */
53 .vi { color: #ff99ff } /* Name.Variable.Instance */
54 .il { color: #009999 } /* Literal.Number.Integer.Long */ No newline at end of file
54 .il { color: #009999 } /* Literal.Number.Integer.Long */
@@ -46,19 +46,17 b' 3. Scale RhodeCode horizontally'
46 large traffic (large amount of users, CI servers etc). RhodeCode can be
46 large traffic (large amount of users, CI servers etc). RhodeCode can be
47 scaled horizontally on one (recommended) or multiple machines. In order
47 scaled horizontally on one (recommended) or multiple machines. In order
48 to scale horizontally you need to do the following:
48 to scale horizontally you need to do the following:
49
49
50 - each instance needs it's own .ini file and unique `instance_id` set in them
50 - each instance needs it's own .ini file and unique `instance_id` set in them
51 - each instance `data` storage needs to be configured to be stored on a
51 - each instance `data` storage needs to be configured to be stored on a
52 shared disk storage, preferably together with repositories. This `data`
52 shared disk storage, preferably together with repositories. This `data`
53 dir contains template caches, sessions, whoosh index and it's used for
53 dir contains template caches, sessions, whoosh index and it's used for
54 tasks locking (so it's safe across multiple instances). Set the
54 tasks locking (so it's safe across multiple instances). Set the
55 `cache_dir`, `index_dir`, `beaker.cache.data_dir`, `beaker.cache.lock_dir`
55 `cache_dir`, `index_dir`, `beaker.cache.data_dir`, `beaker.cache.lock_dir`
56 variables in each .ini file to shared location across RhodeCode instances
56 variables in each .ini file to shared location across RhodeCode instances
57 - if celery is used each instance should run separate celery instance, but
57 - if celery is used each instance should run separate celery instance, but
58 the message broken should be common to all of them (ex one rabbitmq
58 the message broken should be common to all of them (ex one rabbitmq
59 shared server)
59 shared server)
60 - load balance using round robin or ip hash, recommended is writing LB rules
60 - load balance using round robin or ip hash, recommended is writing LB rules
61 that will separate regular user traffic from automated processes like CI
61 that will separate regular user traffic from automated processes like CI
62 servers or build bots.
62 servers or build bots.
63
64
@@ -48,7 +48,7 b' def make_map(config):'
48
48
49 def check_group(environ, match_dict):
49 def check_group(environ, match_dict):
50 """
50 """
51 check for valid repositories group for proper 404 handling
51 check for valid repository group for proper 404 handling
52
52
53 :param environ:
53 :param environ:
54 :param match_dict:
54 :param match_dict:
@@ -235,7 +235,7 b' def make_map(config):'
235 m.connect("user_ips_delete", "/users_ips/{id}",
235 m.connect("user_ips_delete", "/users_ips/{id}",
236 action="delete_ip", conditions=dict(method=["DELETE"]))
236 action="delete_ip", conditions=dict(method=["DELETE"]))
237
237
238 #ADMIN USERS GROUPS REST ROUTES
238 #ADMIN USER GROUPS REST ROUTES
239 with rmap.submapper(path_prefix=ADMIN_PREFIX,
239 with rmap.submapper(path_prefix=ADMIN_PREFIX,
240 controller='admin/users_groups') as m:
240 controller='admin/users_groups') as m:
241 m.connect("users_groups", "/users_groups",
241 m.connect("users_groups", "/users_groups",
@@ -28,7 +28,7 b' import traceback'
28
28
29 from pylons import request
29 from pylons import request
30 from pylons import tmpl_context as c, url
30 from pylons import tmpl_context as c, url
31 from pylons.controllers.util import redirect
31 from pylons.controllers.util import redirect, abort
32
32
33 from webhelpers.paginate import Page
33 from webhelpers.paginate import Page
34
34
@@ -117,7 +117,7 b' class NotificationsController(BaseContro'
117 Session().commit()
117 Session().commit()
118 return 'ok'
118 return 'ok'
119 except Exception:
119 except Exception:
120 Session.rollback()
120 Session().rollback()
121 log.error(traceback.format_exc())
121 log.error(traceback.format_exc())
122 return 'fail'
122 return 'fail'
123
123
@@ -139,7 +139,7 b' class NotificationsController(BaseContro'
139 Session().commit()
139 Session().commit()
140 return 'ok'
140 return 'ok'
141 except Exception:
141 except Exception:
142 Session.rollback()
142 Session().rollback()
143 log.error(traceback.format_exc())
143 log.error(traceback.format_exc())
144 return 'fail'
144 return 'fail'
145
145
@@ -149,8 +149,9 b' class NotificationsController(BaseContro'
149 c.user = self.rhodecode_user
149 c.user = self.rhodecode_user
150 no = Notification.get(notification_id)
150 no = Notification.get(notification_id)
151
151
152 owner = all(un.user.user_id == c.rhodecode_user.user_id
152 owner = any(un.user.user_id == c.rhodecode_user.user_id
153 for un in no.notifications_to_users)
153 for un in no.notifications_to_users)
154
154 if no and (h.HasPermissionAny('hg.admin', 'repository.admin')() or owner):
155 if no and (h.HasPermissionAny('hg.admin', 'repository.admin')() or owner):
155 unotification = NotificationModel()\
156 unotification = NotificationModel()\
156 .get_user_notification(c.user.user_id, no)
157 .get_user_notification(c.user.user_id, no)
@@ -165,7 +166,7 b' class NotificationsController(BaseContro'
165
166
166 return render('admin/notifications/show_notification.html')
167 return render('admin/notifications/show_notification.html')
167
168
168 return redirect(url('notifications'))
169 return abort(403)
169
170
170 def edit(self, notification_id, format='html'):
171 def edit(self, notification_id, format='html'):
171 """GET /_admin/notifications/id/edit: Form to edit an existing item"""
172 """GET /_admin/notifications/id/edit: Form to edit an existing item"""
@@ -345,7 +345,7 b' class ReposController(BaseRepoController'
345 @HasRepoPermissionAllDecorator('repository.admin')
345 @HasRepoPermissionAllDecorator('repository.admin')
346 def delete_perm_users_group(self, repo_name):
346 def delete_perm_users_group(self, repo_name):
347 """
347 """
348 DELETE an existing repository permission users group
348 DELETE an existing repository permission user group
349
349
350 :param repo_name:
350 :param repo_name:
351 """
351 """
@@ -358,7 +358,7 b' class ReposController(BaseRepoController'
358 except Exception:
358 except Exception:
359 log.error(traceback.format_exc())
359 log.error(traceback.format_exc())
360 h.flash(_('An error occurred during deletion of repository'
360 h.flash(_('An error occurred during deletion of repository'
361 ' users groups'),
361 ' user groups'),
362 category='error')
362 category='error')
363 raise HTTPInternalServerError()
363 raise HTTPInternalServerError()
364
364
@@ -3,7 +3,7 b''
3 rhodecode.controllers.admin.repos_groups
3 rhodecode.controllers.admin.repos_groups
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5
5
6 Repositories groups controller for RhodeCode
6 Repository groups controller for RhodeCode
7
7
8 :created_on: Mar 23, 2010
8 :created_on: Mar 23, 2010
9 :author: marcink
9 :author: marcink
@@ -282,7 +282,7 b' class ReposGroupsController(BaseControll'
282 @HasReposGroupPermissionAnyDecorator('group.admin')
282 @HasReposGroupPermissionAnyDecorator('group.admin')
283 def delete_repos_group_user_perm(self, group_name):
283 def delete_repos_group_user_perm(self, group_name):
284 """
284 """
285 DELETE an existing repositories group permission user
285 DELETE an existing repository group permission user
286
286
287 :param group_name:
287 :param group_name:
288 """
288 """
@@ -307,7 +307,7 b' class ReposGroupsController(BaseControll'
307 @HasReposGroupPermissionAnyDecorator('group.admin')
307 @HasReposGroupPermissionAnyDecorator('group.admin')
308 def delete_repos_group_users_group_perm(self, group_name):
308 def delete_repos_group_users_group_perm(self, group_name):
309 """
309 """
310 DELETE an existing repositories group permission users group
310 DELETE an existing repository group permission user group
311
311
312 :param group_name:
312 :param group_name:
313 """
313 """
@@ -322,7 +322,7 b' class ReposGroupsController(BaseControll'
322 except Exception:
322 except Exception:
323 log.error(traceback.format_exc())
323 log.error(traceback.format_exc())
324 h.flash(_('An error occurred during deletion of group'
324 h.flash(_('An error occurred during deletion of group'
325 ' users groups'),
325 ' user groups'),
326 category='error')
326 category='error')
327 raise HTTPInternalServerError()
327 raise HTTPInternalServerError()
328
328
@@ -474,18 +474,23 b' class SettingsController(BaseController)'
474
474
475 @NotAnonymous()
475 @NotAnonymous()
476 def my_account_my_pullrequests(self):
476 def my_account_my_pullrequests(self):
477 c.my_pull_requests = PullRequest.query()\
477 c.show_closed = request.GET.get('pr_show_closed')
478
479 def _filter(pr):
480 s = sorted(pr, key=lambda o: o.created_on, reverse=True)
481 if not c.show_closed:
482 s = filter(lambda p: p.status != PullRequest.STATUS_CLOSED, s)
483 return s
484
485 c.my_pull_requests = _filter(PullRequest.query()\
478 .filter(PullRequest.user_id ==
486 .filter(PullRequest.user_id ==
479 self.rhodecode_user.user_id)\
487 self.rhodecode_user.user_id)\
480 .order_by(PullRequest.created_on.desc())\
488 .all())
481 .all()
482
489
483 c.participate_in_pull_requests = sorted(
490 c.participate_in_pull_requests = _filter([
484 [x.pull_request for x in PullRequestReviewers.query()\
491 x.pull_request for x in PullRequestReviewers.query()\
485 .filter(PullRequestReviewers.user_id ==
492 .filter(PullRequestReviewers.user_id ==
486 self.rhodecode_user.user_id)\
493 self.rhodecode_user.user_id).all()])
487 .all()],
488 key=lambda o: o.created_on, reverse=True)
489
494
490 return render('admin/users/user_edit_my_account_pullrequests.html')
495 return render('admin/users/user_edit_my_account_pullrequests.html')
491
496
@@ -3,7 +3,7 b''
3 rhodecode.controllers.admin.users_groups
3 rhodecode.controllers.admin.users_groups
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5
5
6 Users Groups crud controller for pylons
6 User 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
@@ -33,16 +33,16 b' from pylons.controllers.util import abor'
33 from pylons.i18n.translation import _
33 from pylons.i18n.translation import _
34
34
35 from rhodecode.lib import helpers as h
35 from rhodecode.lib import helpers as h
36 from rhodecode.lib.exceptions import UsersGroupsAssignedException
36 from rhodecode.lib.exceptions import UserGroupsAssignedException
37 from rhodecode.lib.utils2 import safe_unicode, str2bool
37 from rhodecode.lib.utils2 import safe_unicode, str2bool
38 from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator
38 from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator
39 from rhodecode.lib.base import BaseController, render
39 from rhodecode.lib.base import BaseController, render
40
40
41 from rhodecode.model.users_group import UsersGroupModel
41 from rhodecode.model.users_group import UserGroupModel
42
42
43 from rhodecode.model.db import User, UsersGroup, UsersGroupToPerm,\
43 from rhodecode.model.db import User, UserGroup, UserGroupToPerm,\
44 UsersGroupRepoToPerm, UsersGroupRepoGroupToPerm
44 UserGroupRepoToPerm, UserGroupRepoGroupToPerm
45 from rhodecode.model.forms import UsersGroupForm
45 from rhodecode.model.forms import UserGroupForm
46 from rhodecode.model.meta import Session
46 from rhodecode.model.meta import Session
47 from rhodecode.lib.utils import action_logger
47 from rhodecode.lib.utils import action_logger
48 from sqlalchemy.orm import joinedload
48 from sqlalchemy.orm import joinedload
@@ -67,23 +67,23 b' class UsersGroupsController(BaseControll'
67 def index(self, format='html'):
67 def index(self, format='html'):
68 """GET /users_groups: All items in the collection"""
68 """GET /users_groups: All items in the collection"""
69 # url('users_groups')
69 # url('users_groups')
70 c.users_groups_list = UsersGroup().query().all()
70 c.users_groups_list = UserGroup().query().all()
71 return render('admin/users_groups/users_groups.html')
71 return render('admin/users_groups/users_groups.html')
72
72
73 def create(self):
73 def create(self):
74 """POST /users_groups: Create a new item"""
74 """POST /users_groups: Create a new item"""
75 # url('users_groups')
75 # url('users_groups')
76
76
77 users_group_form = UsersGroupForm()()
77 users_group_form = UserGroupForm()()
78 try:
78 try:
79 form_result = users_group_form.to_python(dict(request.POST))
79 form_result = users_group_form.to_python(dict(request.POST))
80 UsersGroupModel().create(name=form_result['users_group_name'],
80 UserGroupModel().create(name=form_result['users_group_name'],
81 active=form_result['users_group_active'])
81 active=form_result['users_group_active'])
82 gr = form_result['users_group_name']
82 gr = form_result['users_group_name']
83 action_logger(self.rhodecode_user,
83 action_logger(self.rhodecode_user,
84 'admin_created_users_group:%s' % gr,
84 'admin_created_users_group:%s' % gr,
85 None, self.ip_addr, self.sa)
85 None, self.ip_addr, self.sa)
86 h.flash(_('created users group %s') % gr, category='success')
86 h.flash(_('created user group %s') % gr, category='success')
87 Session().commit()
87 Session().commit()
88 except formencode.Invalid, errors:
88 except formencode.Invalid, errors:
89 return htmlfill.render(
89 return htmlfill.render(
@@ -94,7 +94,7 b' class UsersGroupsController(BaseControll'
94 encoding="UTF-8")
94 encoding="UTF-8")
95 except Exception:
95 except Exception:
96 log.error(traceback.format_exc())
96 log.error(traceback.format_exc())
97 h.flash(_('error occurred during creation of users group %s') \
97 h.flash(_('error occurred during creation of user group %s') \
98 % request.POST.get('users_group_name'), category='error')
98 % request.POST.get('users_group_name'), category='error')
99
99
100 return redirect(url('users_groups'))
100 return redirect(url('users_groups'))
@@ -110,20 +110,20 b' class UsersGroupsController(BaseControll'
110 'repositories_groups': {}
110 'repositories_groups': {}
111 }
111 }
112
112
113 ugroup_repo_perms = UsersGroupRepoToPerm.query()\
113 ugroup_repo_perms = UserGroupRepoToPerm.query()\
114 .options(joinedload(UsersGroupRepoToPerm.permission))\
114 .options(joinedload(UserGroupRepoToPerm.permission))\
115 .options(joinedload(UsersGroupRepoToPerm.repository))\
115 .options(joinedload(UserGroupRepoToPerm.repository))\
116 .filter(UsersGroupRepoToPerm.users_group_id == id)\
116 .filter(UserGroupRepoToPerm.users_group_id == id)\
117 .all()
117 .all()
118
118
119 for gr in ugroup_repo_perms:
119 for gr in ugroup_repo_perms:
120 c.users_group.permissions['repositories'][gr.repository.repo_name] \
120 c.users_group.permissions['repositories'][gr.repository.repo_name] \
121 = gr.permission.permission_name
121 = gr.permission.permission_name
122
122
123 ugroup_group_perms = UsersGroupRepoGroupToPerm.query()\
123 ugroup_group_perms = UserGroupRepoGroupToPerm.query()\
124 .options(joinedload(UsersGroupRepoGroupToPerm.permission))\
124 .options(joinedload(UserGroupRepoGroupToPerm.permission))\
125 .options(joinedload(UsersGroupRepoGroupToPerm.group))\
125 .options(joinedload(UserGroupRepoGroupToPerm.group))\
126 .filter(UsersGroupRepoGroupToPerm.users_group_id == id)\
126 .filter(UserGroupRepoGroupToPerm.users_group_id == id)\
127 .all()
127 .all()
128
128
129 for gr in ugroup_group_perms:
129 for gr in ugroup_group_perms:
@@ -145,26 +145,26 b' class UsersGroupsController(BaseControll'
145 # method='put')
145 # method='put')
146 # url('users_group', id=ID)
146 # url('users_group', id=ID)
147
147
148 c.users_group = UsersGroup.get_or_404(id)
148 c.users_group = UserGroup.get_or_404(id)
149 self._load_data(id)
149 self._load_data(id)
150
150
151 available_members = [safe_unicode(x[0]) for x in c.available_members]
151 available_members = [safe_unicode(x[0]) for x in c.available_members]
152
152
153 users_group_form = UsersGroupForm(edit=True,
153 users_group_form = UserGroupForm(edit=True,
154 old_data=c.users_group.get_dict(),
154 old_data=c.users_group.get_dict(),
155 available_members=available_members)()
155 available_members=available_members)()
156
156
157 try:
157 try:
158 form_result = users_group_form.to_python(request.POST)
158 form_result = users_group_form.to_python(request.POST)
159 UsersGroupModel().update(c.users_group, form_result)
159 UserGroupModel().update(c.users_group, form_result)
160 gr = form_result['users_group_name']
160 gr = form_result['users_group_name']
161 action_logger(self.rhodecode_user,
161 action_logger(self.rhodecode_user,
162 'admin_updated_users_group:%s' % gr,
162 'admin_updated_users_group:%s' % gr,
163 None, self.ip_addr, self.sa)
163 None, self.ip_addr, self.sa)
164 h.flash(_('updated users group %s') % gr, category='success')
164 h.flash(_('updated user group %s') % gr, category='success')
165 Session().commit()
165 Session().commit()
166 except formencode.Invalid, errors:
166 except formencode.Invalid, errors:
167 ug_model = UsersGroupModel()
167 ug_model = UserGroupModel()
168 defaults = errors.value
168 defaults = errors.value
169 e = errors.error_dict or {}
169 e = errors.error_dict or {}
170 defaults.update({
170 defaults.update({
@@ -183,7 +183,7 b' class UsersGroupsController(BaseControll'
183 encoding="UTF-8")
183 encoding="UTF-8")
184 except Exception:
184 except Exception:
185 log.error(traceback.format_exc())
185 log.error(traceback.format_exc())
186 h.flash(_('error occurred during update of users group %s') \
186 h.flash(_('error occurred during update of user group %s') \
187 % request.POST.get('users_group_name'), category='error')
187 % request.POST.get('users_group_name'), category='error')
188
188
189 return redirect(url('edit_users_group', id=id))
189 return redirect(url('edit_users_group', id=id))
@@ -196,16 +196,16 b' class UsersGroupsController(BaseControll'
196 # h.form(url('users_group', id=ID),
196 # h.form(url('users_group', id=ID),
197 # method='delete')
197 # method='delete')
198 # url('users_group', id=ID)
198 # url('users_group', id=ID)
199 usr_gr = UsersGroup.get_or_404(id)
199 usr_gr = UserGroup.get_or_404(id)
200 try:
200 try:
201 UsersGroupModel().delete(usr_gr)
201 UserGroupModel().delete(usr_gr)
202 Session().commit()
202 Session().commit()
203 h.flash(_('successfully deleted users group'), category='success')
203 h.flash(_('successfully deleted user group'), category='success')
204 except UsersGroupsAssignedException, e:
204 except UserGroupsAssignedException, e:
205 h.flash(e, category='error')
205 h.flash(e, category='error')
206 except Exception:
206 except Exception:
207 log.error(traceback.format_exc())
207 log.error(traceback.format_exc())
208 h.flash(_('An error occurred during deletion of users group'),
208 h.flash(_('An error occurred during deletion of user group'),
209 category='error')
209 category='error')
210 return redirect(url('users_groups'))
210 return redirect(url('users_groups'))
211
211
@@ -217,10 +217,10 b' class UsersGroupsController(BaseControll'
217 """GET /users_groups/id/edit: Form to edit an existing item"""
217 """GET /users_groups/id/edit: Form to edit an existing item"""
218 # url('edit_users_group', id=ID)
218 # url('edit_users_group', id=ID)
219
219
220 c.users_group = UsersGroup.get_or_404(id)
220 c.users_group = UserGroup.get_or_404(id)
221 self._load_data(id)
221 self._load_data(id)
222
222
223 ug_model = UsersGroupModel()
223 ug_model = UserGroupModel()
224 defaults = c.users_group.get_dict()
224 defaults = c.users_group.get_dict()
225 defaults.update({
225 defaults.update({
226 'create_repo_perm': ug_model.has_perm(c.users_group,
226 'create_repo_perm': ug_model.has_perm(c.users_group,
@@ -240,37 +240,37 b' class UsersGroupsController(BaseControll'
240 """PUT /users_perm/id: Update an existing item"""
240 """PUT /users_perm/id: Update an existing item"""
241 # url('users_group_perm', id=ID, method='put')
241 # url('users_group_perm', id=ID, method='put')
242
242
243 users_group = UsersGroup.get_or_404(id)
243 users_group = UserGroup.get_or_404(id)
244 grant_create_perm = str2bool(request.POST.get('create_repo_perm'))
244 grant_create_perm = str2bool(request.POST.get('create_repo_perm'))
245 grant_fork_perm = str2bool(request.POST.get('fork_repo_perm'))
245 grant_fork_perm = str2bool(request.POST.get('fork_repo_perm'))
246 inherit_perms = str2bool(request.POST.get('inherit_default_permissions'))
246 inherit_perms = str2bool(request.POST.get('inherit_default_permissions'))
247
247
248 usersgroup_model = UsersGroupModel()
248 usergroup_model = UserGroupModel()
249
249
250 try:
250 try:
251 users_group.inherit_default_permissions = inherit_perms
251 users_group.inherit_default_permissions = inherit_perms
252 Session().add(users_group)
252 Session().add(users_group)
253
253
254 if grant_create_perm:
254 if grant_create_perm:
255 usersgroup_model.revoke_perm(id, 'hg.create.none')
255 usergroup_model.revoke_perm(id, 'hg.create.none')
256 usersgroup_model.grant_perm(id, 'hg.create.repository')
256 usergroup_model.grant_perm(id, 'hg.create.repository')
257 h.flash(_("Granted 'repository create' permission to users group"),
257 h.flash(_("Granted 'repository create' permission to user group"),
258 category='success')
258 category='success')
259 else:
259 else:
260 usersgroup_model.revoke_perm(id, 'hg.create.repository')
260 usergroup_model.revoke_perm(id, 'hg.create.repository')
261 usersgroup_model.grant_perm(id, 'hg.create.none')
261 usergroup_model.grant_perm(id, 'hg.create.none')
262 h.flash(_("Revoked 'repository create' permission to users group"),
262 h.flash(_("Revoked 'repository create' permission to user group"),
263 category='success')
263 category='success')
264
264
265 if grant_fork_perm:
265 if grant_fork_perm:
266 usersgroup_model.revoke_perm(id, 'hg.fork.none')
266 usergroup_model.revoke_perm(id, 'hg.fork.none')
267 usersgroup_model.grant_perm(id, 'hg.fork.repository')
267 usergroup_model.grant_perm(id, 'hg.fork.repository')
268 h.flash(_("Granted 'repository fork' permission to users group"),
268 h.flash(_("Granted 'repository fork' permission to user group"),
269 category='success')
269 category='success')
270 else:
270 else:
271 usersgroup_model.revoke_perm(id, 'hg.fork.repository')
271 usergroup_model.revoke_perm(id, 'hg.fork.repository')
272 usersgroup_model.grant_perm(id, 'hg.fork.none')
272 usergroup_model.grant_perm(id, 'hg.fork.none')
273 h.flash(_("Revoked 'repository fork' permission to users group"),
273 h.flash(_("Revoked 'repository fork' permission to user group"),
274 category='success')
274 category='success')
275
275
276 Session().commit()
276 Session().commit()
@@ -34,11 +34,12 b' from rhodecode.lib.auth import PasswordG'
34 HasPermissionAllDecorator, HasPermissionAnyDecorator, \
34 HasPermissionAllDecorator, HasPermissionAnyDecorator, \
35 HasPermissionAnyApi, HasRepoPermissionAnyApi
35 HasPermissionAnyApi, HasRepoPermissionAnyApi
36 from rhodecode.lib.utils import map_groups, repo2db_mapper
36 from rhodecode.lib.utils import map_groups, repo2db_mapper
37 from rhodecode.lib.utils2 import str2bool
37 from rhodecode.model.meta import Session
38 from rhodecode.model.meta import Session
38 from rhodecode.model.scm import ScmModel
39 from rhodecode.model.scm import ScmModel
39 from rhodecode.model.repo import RepoModel
40 from rhodecode.model.repo import RepoModel
40 from rhodecode.model.user import UserModel
41 from rhodecode.model.user import UserModel
41 from rhodecode.model.users_group import UsersGroupModel
42 from rhodecode.model.users_group import UserGroupModel
42 from rhodecode.model.permission import PermissionModel
43 from rhodecode.model.permission import PermissionModel
43 from rhodecode.model.db import Repository, RhodeCodeSetting, UserIpMap
44 from rhodecode.model.db import Repository, RhodeCodeSetting, UserIpMap
44
45
@@ -121,13 +122,13 b' def get_repo_or_error(repoid):'
121
122
122 def get_users_group_or_error(usersgroupid):
123 def get_users_group_or_error(usersgroupid):
123 """
124 """
124 Get users group by id or name or return JsonRPCError if not found
125 Get user group by id or name or return JsonRPCError if not found
125
126
126 :param userid:
127 :param userid:
127 """
128 """
128 users_group = UsersGroupModel().get_group(usersgroupid)
129 users_group = UserGroupModel().get_group(usersgroupid)
129 if users_group is None:
130 if users_group is None:
130 raise JSONRPCError('users group `%s` does not exist' % usersgroupid)
131 raise JSONRPCError('user group `%s` does not exist' % usersgroupid)
131 return users_group
132 return users_group
132
133
133
134
@@ -257,7 +258,7 b' class ApiController(JSONRPCController):'
257 if isinstance(userid, Optional):
258 if isinstance(userid, Optional):
258 userid = apiuser.user_id
259 userid = apiuser.user_id
259 user = get_user_or_error(userid)
260 user = get_user_or_error(userid)
260 locked = bool(locked)
261 locked = str2bool(locked)
261 try:
262 try:
262 if locked:
263 if locked:
263 Repository.lock(repo, user.user_id)
264 Repository.lock(repo, user.user_id)
@@ -449,7 +450,7 b' class ApiController(JSONRPCController):'
449 @HasPermissionAllDecorator('hg.admin')
450 @HasPermissionAllDecorator('hg.admin')
450 def get_users_group(self, apiuser, usersgroupid):
451 def get_users_group(self, apiuser, usersgroupid):
451 """"
452 """"
452 Get users group by name or id
453 Get user group by name or id
453
454
454 :param apiuser:
455 :param apiuser:
455 :param usersgroupid:
456 :param usersgroupid:
@@ -468,13 +469,13 b' class ApiController(JSONRPCController):'
468 @HasPermissionAllDecorator('hg.admin')
469 @HasPermissionAllDecorator('hg.admin')
469 def get_users_groups(self, apiuser):
470 def get_users_groups(self, apiuser):
470 """"
471 """"
471 Get all users groups
472 Get all user groups
472
473
473 :param apiuser:
474 :param apiuser:
474 """
475 """
475
476
476 result = []
477 result = []
477 for users_group in UsersGroupModel().get_all():
478 for users_group in UserGroupModel().get_all():
478 result.append(users_group.get_api_data())
479 result.append(users_group.get_api_data())
479 return result
480 return result
480
481
@@ -488,15 +489,15 b' class ApiController(JSONRPCController):'
488 :param active:
489 :param active:
489 """
490 """
490
491
491 if UsersGroupModel().get_by_name(group_name):
492 if UserGroupModel().get_by_name(group_name):
492 raise JSONRPCError("users group `%s` already exist" % group_name)
493 raise JSONRPCError("user group `%s` already exist" % group_name)
493
494
494 try:
495 try:
495 active = Optional.extract(active)
496 active = Optional.extract(active)
496 ug = UsersGroupModel().create(name=group_name, active=active)
497 ug = UserGroupModel().create(name=group_name, active=active)
497 Session().commit()
498 Session().commit()
498 return dict(
499 return dict(
499 msg='created new users group `%s`' % group_name,
500 msg='created new user group `%s`' % group_name,
500 users_group=ug.get_api_data()
501 users_group=ug.get_api_data()
501 )
502 )
502 except Exception:
503 except Exception:
@@ -506,7 +507,7 b' class ApiController(JSONRPCController):'
506 @HasPermissionAllDecorator('hg.admin')
507 @HasPermissionAllDecorator('hg.admin')
507 def add_user_to_users_group(self, apiuser, usersgroupid, userid):
508 def add_user_to_users_group(self, apiuser, usersgroupid, userid):
508 """"
509 """"
509 Add a user to a users group
510 Add a user to a user group
510
511
511 :param apiuser:
512 :param apiuser:
512 :param usersgroupid:
513 :param usersgroupid:
@@ -516,9 +517,9 b' class ApiController(JSONRPCController):'
516 users_group = get_users_group_or_error(usersgroupid)
517 users_group = get_users_group_or_error(usersgroupid)
517
518
518 try:
519 try:
519 ugm = UsersGroupModel().add_user_to_group(users_group, user)
520 ugm = UserGroupModel().add_user_to_group(users_group, user)
520 success = True if ugm != True else False
521 success = True if ugm != True else False
521 msg = 'added member `%s` to users group `%s`' % (
522 msg = 'added member `%s` to user group `%s`' % (
522 user.username, users_group.users_group_name
523 user.username, users_group.users_group_name
523 )
524 )
524 msg = msg if success else 'User is already in that group'
525 msg = msg if success else 'User is already in that group'
@@ -531,7 +532,7 b' class ApiController(JSONRPCController):'
531 except Exception:
532 except Exception:
532 log.error(traceback.format_exc())
533 log.error(traceback.format_exc())
533 raise JSONRPCError(
534 raise JSONRPCError(
534 'failed to add member to users group `%s`' % (
535 'failed to add member to user group `%s`' % (
535 users_group.users_group_name
536 users_group.users_group_name
536 )
537 )
537 )
538 )
@@ -549,9 +550,9 b' class ApiController(JSONRPCController):'
549 users_group = get_users_group_or_error(usersgroupid)
550 users_group = get_users_group_or_error(usersgroupid)
550
551
551 try:
552 try:
552 success = UsersGroupModel().remove_user_from_group(users_group,
553 success = UserGroupModel().remove_user_from_group(users_group,
553 user)
554 user)
554 msg = 'removed member `%s` from users group `%s`' % (
555 msg = 'removed member `%s` from user group `%s`' % (
555 user.username, users_group.users_group_name
556 user.username, users_group.users_group_name
556 )
557 )
557 msg = msg if success else "User wasn't in group"
558 msg = msg if success else "User wasn't in group"
@@ -560,7 +561,7 b' class ApiController(JSONRPCController):'
560 except Exception:
561 except Exception:
561 log.error(traceback.format_exc())
562 log.error(traceback.format_exc())
562 raise JSONRPCError(
563 raise JSONRPCError(
563 'failed to remove member from users group `%s`' % (
564 'failed to remove member from user group `%s`' % (
564 users_group.users_group_name
565 users_group.users_group_name
565 )
566 )
566 )
567 )
@@ -890,7 +891,7 b' class ApiController(JSONRPCController):'
890 def grant_users_group_permission(self, apiuser, repoid, usersgroupid,
891 def grant_users_group_permission(self, apiuser, repoid, usersgroupid,
891 perm):
892 perm):
892 """
893 """
893 Grant permission for users group on given repository, or update
894 Grant permission for user group on given repository, or update
894 existing one if found
895 existing one if found
895
896
896 :param apiuser:
897 :param apiuser:
@@ -909,7 +910,7 b' class ApiController(JSONRPCController):'
909
910
910 Session().commit()
911 Session().commit()
911 return dict(
912 return dict(
912 msg='Granted perm: `%s` for users group: `%s` in '
913 msg='Granted perm: `%s` for user group: `%s` in '
913 'repo: `%s`' % (
914 'repo: `%s`' % (
914 perm.permission_name, users_group.users_group_name,
915 perm.permission_name, users_group.users_group_name,
915 repo.repo_name
916 repo.repo_name
@@ -919,7 +920,7 b' class ApiController(JSONRPCController):'
919 except Exception:
920 except Exception:
920 log.error(traceback.format_exc())
921 log.error(traceback.format_exc())
921 raise JSONRPCError(
922 raise JSONRPCError(
922 'failed to edit permission for users group: `%s` in '
923 'failed to edit permission for user group: `%s` in '
923 'repo: `%s`' % (
924 'repo: `%s`' % (
924 usersgroupid, repo.repo_name
925 usersgroupid, repo.repo_name
925 )
926 )
@@ -928,7 +929,7 b' class ApiController(JSONRPCController):'
928 @HasPermissionAllDecorator('hg.admin')
929 @HasPermissionAllDecorator('hg.admin')
929 def revoke_users_group_permission(self, apiuser, repoid, usersgroupid):
930 def revoke_users_group_permission(self, apiuser, repoid, usersgroupid):
930 """
931 """
931 Revoke permission for users group on given repository
932 Revoke permission for user group on given repository
932
933
933 :param apiuser:
934 :param apiuser:
934 :param repoid:
935 :param repoid:
@@ -943,7 +944,7 b' class ApiController(JSONRPCController):'
943
944
944 Session().commit()
945 Session().commit()
945 return dict(
946 return dict(
946 msg='Revoked perm for users group: `%s` in repo: `%s`' % (
947 msg='Revoked perm for user group: `%s` in repo: `%s`' % (
947 users_group.users_group_name, repo.repo_name
948 users_group.users_group_name, repo.repo_name
948 ),
949 ),
949 success=True
950 success=True
@@ -951,7 +952,7 b' class ApiController(JSONRPCController):'
951 except Exception:
952 except Exception:
952 log.error(traceback.format_exc())
953 log.error(traceback.format_exc())
953 raise JSONRPCError(
954 raise JSONRPCError(
954 'failed to edit permission for users group: `%s` in '
955 'failed to edit permission for user group: `%s` in '
955 'repo: `%s`' % (
956 'repo: `%s`' % (
956 users_group.users_group_name, repo.repo_name
957 users_group.users_group_name, repo.repo_name
957 )
958 )
@@ -329,7 +329,7 b' class ChangesetController(BaseRepoContro'
329 text = text or (_('Status change -> %s')
329 text = text or (_('Status change -> %s')
330 % ChangesetStatus.get_status_lbl(status))
330 % ChangesetStatus.get_status_lbl(status))
331
331
332 comm = ChangesetCommentsModel().create(
332 c.co = comm = ChangesetCommentsModel().create(
333 text=text,
333 text=text,
334 repo=c.rhodecode_db_repo.repo_id,
334 repo=c.rhodecode_db_repo.repo_id,
335 user=c.rhodecode_user.user_id,
335 user=c.rhodecode_user.user_id,
@@ -371,12 +371,11 b' class ChangesetController(BaseRepoContro'
371 if not request.environ.get('HTTP_X_PARTIAL_XHR'):
371 if not request.environ.get('HTTP_X_PARTIAL_XHR'):
372 return redirect(h.url('changeset_home', repo_name=repo_name,
372 return redirect(h.url('changeset_home', repo_name=repo_name,
373 revision=revision))
373 revision=revision))
374
374 #only ajax below
375 data = {
375 data = {
376 'target_id': h.safeid(h.safe_unicode(request.POST.get('f_path'))),
376 'target_id': h.safeid(h.safe_unicode(request.POST.get('f_path'))),
377 }
377 }
378 if comm:
378 if comm:
379 c.co = comm
380 data.update(comm.get_dict())
379 data.update(comm.get_dict())
381 data.update({'rendered_text':
380 data.update({'rendered_text':
382 render('changeset/changeset_comment_block.html')})
381 render('changeset/changeset_comment_block.html')})
@@ -83,23 +83,28 b' class CompareController(BaseRepoControll'
83 raise HTTPBadRequest()
83 raise HTTPBadRequest()
84
84
85 def index(self, org_ref_type, org_ref, other_ref_type, other_ref):
85 def index(self, org_ref_type, org_ref, other_ref_type, other_ref):
86
86 # org_ref will be evaluated in org_repo
87 org_repo = c.rhodecode_db_repo.repo_name
87 org_repo = c.rhodecode_db_repo.repo_name
88 org_ref = (org_ref_type, org_ref)
88 org_ref = (org_ref_type, org_ref)
89 # other_ref will be evaluated in other_repo
89 other_ref = (other_ref_type, other_ref)
90 other_ref = (other_ref_type, other_ref)
90 other_repo = request.GET.get('other_repo', org_repo)
91 other_repo = request.GET.get('other_repo', org_repo)
91 c.fulldiff = fulldiff = request.GET.get('fulldiff')
92 # fulldiff disables cut_off_limit
93 c.fulldiff = request.GET.get('fulldiff')
94 # only consider this range of changesets
92 rev_start = request.GET.get('rev_start')
95 rev_start = request.GET.get('rev_start')
93 rev_end = request.GET.get('rev_end')
96 rev_end = request.GET.get('rev_end')
94
97 # partial uses compare_cs.html template directly
95 c.swap_url = h.url('compare_url', as_form=request.GET.get('as_form'),
98 partial = request.environ.get('HTTP_X_PARTIAL_XHR')
99 # as_form puts hidden input field with changeset revisions
100 c.as_form = partial and request.GET.get('as_form')
101 # swap url for compare_diff page - never partial and never as_form
102 c.swap_url = h.url('compare_url',
96 repo_name=other_repo,
103 repo_name=other_repo,
97 org_ref_type=other_ref[0], org_ref=other_ref[1],
104 org_ref_type=other_ref[0], org_ref=other_ref[1],
98 other_repo=org_repo,
105 other_repo=org_repo,
99 other_ref_type=org_ref[0], other_ref=org_ref[1])
106 other_ref_type=org_ref[0], other_ref=org_ref[1])
100
107
101 partial = request.environ.get('HTTP_X_PARTIAL_XHR')
102
103 org_repo = Repository.get_by_repo_name(org_repo)
108 org_repo = Repository.get_by_repo_name(org_repo)
104 other_repo = Repository.get_by_repo_name(other_repo)
109 other_repo = Repository.get_by_repo_name(other_repo)
105
110
@@ -148,8 +153,6 b' class CompareController(BaseRepoControll'
148
153
149 c.statuses = c.rhodecode_db_repo.statuses([x.raw_id for x in
154 c.statuses = c.rhodecode_db_repo.statuses([x.raw_id for x in
150 c.cs_ranges])
155 c.cs_ranges])
151 # defines that we need hidden inputs with changesets
152 c.as_form = request.GET.get('as_form', False)
153 if partial:
156 if partial:
154 return render('compare/compare_cs.html')
157 return render('compare/compare_cs.html')
155
158
@@ -163,7 +166,7 b' class CompareController(BaseRepoControll'
163 org_ref = ('rev', ancestor)
166 org_ref = ('rev', ancestor)
164 org_repo = other_repo
167 org_repo = other_repo
165
168
166 diff_limit = self.cut_off_limit if not fulldiff else None
169 diff_limit = self.cut_off_limit if not c.fulldiff else None
167
170
168 _diff = diffs.differ(org_repo, org_ref, other_repo, other_ref)
171 _diff = diffs.differ(org_repo, org_ref, other_repo, other_ref)
169
172
@@ -486,6 +486,8 b' class FilesController(BaseRepoController'
486 c.changeset_1 = c.rhodecode_repo.get_changeset(diff1)
486 c.changeset_1 = c.rhodecode_repo.get_changeset(diff1)
487 try:
487 try:
488 node1 = c.changeset_1.get_node(f_path)
488 node1 = c.changeset_1.get_node(f_path)
489 if node1.is_dir():
490 raise NodeError('%s path is a %s not a file' % (node1, type(node1)))
489 except NodeDoesNotExistError:
491 except NodeDoesNotExistError:
490 c.changeset_1 = EmptyChangeset(cs=diff1,
492 c.changeset_1 = EmptyChangeset(cs=diff1,
491 revision=c.changeset_1.revision,
493 revision=c.changeset_1.revision,
@@ -499,6 +501,7 b' class FilesController(BaseRepoController'
499 c.changeset_2 = c.rhodecode_repo.get_changeset(diff2)
501 c.changeset_2 = c.rhodecode_repo.get_changeset(diff2)
500 try:
502 try:
501 node2 = c.changeset_2.get_node(f_path)
503 node2 = c.changeset_2.get_node(f_path)
504 raise NodeError('%s path is a %s not a file' % (node2, type(node2)))
502 except NodeDoesNotExistError:
505 except NodeDoesNotExistError:
503 c.changeset_2 = EmptyChangeset(cs=diff2,
506 c.changeset_2 = EmptyChangeset(cs=diff2,
504 revision=c.changeset_2.revision,
507 revision=c.changeset_2.revision,
@@ -81,7 +81,7 b' class HomeController(BaseController):'
81 def branch_tag_switcher(self, repo_name):
81 def branch_tag_switcher(self, repo_name):
82 if request.is_xhr:
82 if request.is_xhr:
83 c.rhodecode_db_repo = Repository.get_by_repo_name(c.repo_name)
83 c.rhodecode_db_repo = Repository.get_by_repo_name(c.repo_name)
84 c.rhodecode_repo = c.rhodecode_db_repo.scm_instance
84 if c.rhodecode_db_repo:
85 return render('/switch_to_list.html')
85 c.rhodecode_repo = c.rhodecode_db_repo.scm_instance
86 else:
86 return render('/switch_to_list.html')
87 raise HTTPBadRequest()
87 raise HTTPBadRequest()
@@ -67,29 +67,33 b' class PullrequestsController(BaseRepoCon'
67 c.users_array = repo_model.get_users_js()
67 c.users_array = repo_model.get_users_js()
68 c.users_groups_array = repo_model.get_users_groups_js()
68 c.users_groups_array = repo_model.get_users_groups_js()
69
69
70 def _get_repo_refs(self, repo):
70 def _get_repo_refs(self, repo, rev=None):
71 hist_l = []
71 """return a structure with repo's interesting changesets, suitable for
72
72 the selectors in pullrequest.html"""
73 branches_group = ([('branch:%s:%s' % (k, v), k) for
73 branches = [('branch:%s:%s' % (k, v), k)
74 k, v in repo.branches.iteritems()], _("Branches"))
74 for k, v in repo.branches.iteritems()]
75 bookmarks_group = ([('book:%s:%s' % (k, v), k) for
75 bookmarks = [('book:%s:%s' % (k, v), k)
76 k, v in repo.bookmarks.iteritems()], _("Bookmarks"))
76 for k, v in repo.bookmarks.iteritems()]
77 tags_group = ([('tag:%s:%s' % (k, v), k) for
77 tags = [('tag:%s:%s' % (k, v), k)
78 k, v in repo.tags.iteritems()
78 for k, v in repo.tags.iteritems()
79 if k != 'tip'], _("Tags"))
79 if k != 'tip']
80
80
81 tip = repo.tags['tip']
81 tip = repo.tags['tip']
82 tipref = 'tag:tip:%s' % tip
83 colontip = ':' + tip
82 colontip = ':' + tip
84 tips = [x[1] for x in branches_group[0] + bookmarks_group[0] + tags_group[0]
83 tips = [x[1] for x in branches + bookmarks + tags
85 if x[0].endswith(colontip)]
84 if x[0].endswith(colontip)]
86 tags_group[0].append((tipref, 'tip (%s)' % ', '.join(tips)))
85 selected = 'tag:tip:%s' % tip
86 special = [(selected, 'tip (%s)' % ', '.join(tips))]
87
87
88 hist_l.append(bookmarks_group)
88 if rev:
89 hist_l.append(branches_group)
89 selected = 'rev:%s:%s' % (rev, rev)
90 hist_l.append(tags_group)
90 special.append((selected, rev))
91
91
92 return hist_l, tipref
92 return [(special, _("Special")),
93 (bookmarks, _("Bookmarks")),
94 (branches, _("Branches")),
95 (tags, _("Tags")),
96 ], selected
93
97
94 def _get_is_allowed_change_status(self, pull_request):
98 def _get_is_allowed_change_status(self, pull_request):
95 owner = self.rhodecode_user.user_id == pull_request.user_id
99 owner = self.rhodecode_user.user_id == pull_request.user_id
@@ -291,8 +295,6 b' class PullrequestsController(BaseRepoCon'
291 else EmptyChangeset(), 'raw_id'))
295 else EmptyChangeset(), 'raw_id'))
292
296
293 c.statuses = org_repo.statuses([x.raw_id for x in c.cs_ranges])
297 c.statuses = org_repo.statuses([x.raw_id for x in c.cs_ranges])
294 # defines that we need hidden inputs with changesets
295 c.as_form = request.GET.get('as_form', False)
296
298
297 c.org_ref = org_ref[1]
299 c.org_ref = org_ref[1]
298 c.org_ref_type = org_ref[0]
300 c.org_ref_type = org_ref[0]
@@ -391,6 +393,7 b' class PullrequestsController(BaseRepoCon'
391 )
393 )
392 c.changeset_statuses = ChangesetStatus.STATUSES
394 c.changeset_statuses = ChangesetStatus.STATUSES
393
395
396 c.as_form = False
394 return render('/pullrequests/pullrequest_show.html')
397 return render('/pullrequests/pullrequest_show.html')
395
398
396 @NotAnonymous()
399 @NotAnonymous()
@@ -403,11 +406,15 b' class PullrequestsController(BaseRepoCon'
403 status = request.POST.get('changeset_status')
406 status = request.POST.get('changeset_status')
404 change_status = request.POST.get('change_changeset_status')
407 change_status = request.POST.get('change_changeset_status')
405 text = request.POST.get('text')
408 text = request.POST.get('text')
409 close_pr = request.POST.get('save_close')
406
410
407 allowed_to_change_status = self._get_is_allowed_change_status(pull_request)
411 allowed_to_change_status = self._get_is_allowed_change_status(pull_request)
408 if status and change_status and allowed_to_change_status:
412 if status and change_status and allowed_to_change_status:
409 text = text or (_('Status change -> %s')
413 _def = (_('status change -> %s')
410 % ChangesetStatus.get_status_lbl(status))
414 % ChangesetStatus.get_status_lbl(status))
415 if close_pr:
416 _def = _('Closing with') + ' ' + _def
417 text = text or _def
411 comm = ChangesetCommentsModel().create(
418 comm = ChangesetCommentsModel().create(
412 text=text,
419 text=text,
413 repo=c.rhodecode_db_repo.repo_id,
420 repo=c.rhodecode_db_repo.repo_id,
@@ -416,7 +423,9 b' class PullrequestsController(BaseRepoCon'
416 f_path=request.POST.get('f_path'),
423 f_path=request.POST.get('f_path'),
417 line_no=request.POST.get('line'),
424 line_no=request.POST.get('line'),
418 status_change=(ChangesetStatus.get_status_lbl(status)
425 status_change=(ChangesetStatus.get_status_lbl(status)
419 if status and change_status and allowed_to_change_status else None)
426 if status and change_status
427 and allowed_to_change_status else None),
428 closing_pr=close_pr
420 )
429 )
421
430
422 action_logger(self.rhodecode_user,
431 action_logger(self.rhodecode_user,
@@ -434,7 +443,7 b' class PullrequestsController(BaseRepoCon'
434 pull_request=pull_request_id
443 pull_request=pull_request_id
435 )
444 )
436
445
437 if request.POST.get('save_close'):
446 if close_pr:
438 if status in ['rejected', 'approved']:
447 if status in ['rejected', 'approved']:
439 PullRequestModel().close_pull_request(pull_request_id)
448 PullRequestModel().close_pull_request(pull_request_id)
440 action_logger(self.rhodecode_user,
449 action_logger(self.rhodecode_user,
@@ -411,7 +411,7 b' class AuthUser(object):'
411 @property
411 @property
412 def groups_admin(self):
412 def groups_admin(self):
413 """
413 """
414 Returns list of repositories groups you're an admin of
414 Returns list of repository groups you're an admin of
415 """
415 """
416 return [x[0] for x in self.permissions['repositories_groups'].iteritems()
416 return [x[0] for x in self.permissions['repositories_groups'].iteritems()
417 if x[1] == 'group.admin']
417 if x[1] == 'group.admin']
@@ -68,6 +68,8 b' def run_task(task, *args, **kwargs):'
68 except socket.error, e:
68 except socket.error, e:
69 if isinstance(e, IOError) and e.errno == 111:
69 if isinstance(e, IOError) and e.errno == 111:
70 log.debug('Unable to connect to celeryd. Sync execution')
70 log.debug('Unable to connect to celeryd. Sync execution')
71 global CELERY_ON
72 CELERY_ON = False
71 else:
73 else:
72 log.error(traceback.format_exc())
74 log.error(traceback.format_exc())
73 except KeyError, e:
75 except KeyError, e:
@@ -251,76 +251,10 b' def get_commits_stats(repo_name, ts_min_'
251 log.info('LockHeld')
251 log.info('LockHeld')
252 return 'Task with key %s already running' % lockkey
252 return 'Task with key %s already running' % lockkey
253
253
254 @task(ignore_result=True)
255 @dbsession
256 def send_password_link(user_email):
257 from rhodecode.model.notification import EmailNotificationModel
258
259 log = get_logger(send_password_link)
260 DBS = get_session()
261
262 try:
263 user = User.get_by_email(user_email)
264 if user:
265 log.debug('password reset user found %s' % user)
266 link = url('reset_password_confirmation', key=user.api_key,
267 qualified=True)
268 reg_type = EmailNotificationModel.TYPE_PASSWORD_RESET
269 body = EmailNotificationModel().get_email_tmpl(reg_type,
270 **{'user':user.short_contact,
271 'reset_url':link})
272 log.debug('sending email')
273 run_task(send_email, user_email,
274 _("password reset link"), body)
275 log.info('send new password mail to %s' % user_email)
276 else:
277 log.debug("password reset email %s not found" % user_email)
278 except:
279 log.error(traceback.format_exc())
280 return False
281
282 return True
283
254
284 @task(ignore_result=True)
255 @task(ignore_result=True)
285 @dbsession
256 @dbsession
286 def reset_user_password(user_email):
257 def send_email(recipients, subject, body='', html_body=''):
287 from rhodecode.lib import auth
288
289 log = get_logger(reset_user_password)
290 DBS = get_session()
291
292 try:
293 try:
294 user = User.get_by_email(user_email)
295 new_passwd = auth.PasswordGenerator().gen_password(8,
296 auth.PasswordGenerator.ALPHABETS_BIG_SMALL)
297 if user:
298 user.password = auth.get_crypt_password(new_passwd)
299 user.api_key = auth.generate_api_key(user.username)
300 DBS.add(user)
301 DBS.commit()
302 log.info('change password for %s' % user_email)
303 if new_passwd is None:
304 raise Exception('unable to generate new password')
305 except:
306 log.error(traceback.format_exc())
307 DBS.rollback()
308
309 run_task(send_email, user_email,
310 'Your new password',
311 'Your new RhodeCode password:%s' % (new_passwd))
312 log.info('send new password mail to %s' % user_email)
313
314 except:
315 log.error('Failed to update user password')
316 log.error(traceback.format_exc())
317
318 return True
319
320
321 @task(ignore_result=True)
322 @dbsession
323 def send_email(recipients, subject, body, html_body=''):
324 """
258 """
325 Sends an email with defined parameters from the .ini files.
259 Sends an email with defined parameters from the .ini files.
326
260
@@ -348,7 +282,7 b' def send_email(recipients, subject, body'
348 mail_port = email_config.get('smtp_port')
282 mail_port = email_config.get('smtp_port')
349 tls = str2bool(email_config.get('smtp_use_tls'))
283 tls = str2bool(email_config.get('smtp_use_tls'))
350 ssl = str2bool(email_config.get('smtp_use_ssl'))
284 ssl = str2bool(email_config.get('smtp_use_ssl'))
351 debug = str2bool(config.get('debug'))
285 debug = str2bool(email_config.get('debug'))
352 smtp_auth = email_config.get('smtp_auth')
286 smtp_auth = email_config.get('smtp_auth')
353
287
354 if not mail_server:
288 if not mail_server:
@@ -41,7 +41,7 b' from rhodecode.lib.vcs.utils.lazy import'
41
41
42 from rhodecode.lib.utils2 import str2bool, safe_str, get_changeset_safe, \
42 from rhodecode.lib.utils2 import str2bool, safe_str, get_changeset_safe, \
43 generate_api_key, safe_unicode
43 generate_api_key, safe_unicode
44 from rhodecode.lib.exceptions import UsersGroupsAssignedException
44 from rhodecode.lib.exceptions import UserGroupsAssignedException
45 from rhodecode.lib.compat import json
45 from rhodecode.lib.compat import json
46
46
47 from rhodecode.model.meta import Base, Session
47 from rhodecode.model.meta import Base, Session
@@ -282,7 +282,7 b' class User(Base, BaseModel):'
282 user_followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_user_id==User.user_id', cascade='all')
282 user_followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_user_id==User.user_id', cascade='all')
283 repo_to_perm = relationship('UserRepoToPerm', primaryjoin='UserRepoToPerm.user_id==User.user_id', cascade='all')
283 repo_to_perm = relationship('UserRepoToPerm', primaryjoin='UserRepoToPerm.user_id==User.user_id', cascade='all')
284
284
285 group_member = relationship('UsersGroupMember', cascade='all')
285 group_member = relationship('UserGroupMember', cascade='all')
286
286
287 @property
287 @property
288 def full_contact(self):
288 def full_contact(self):
@@ -361,7 +361,7 b' class UserLog(Base, BaseModel):'
361 repository = relationship('Repository')
361 repository = relationship('Repository')
362
362
363
363
364 class UsersGroup(Base, BaseModel):
364 class UserGroup(Base, BaseModel):
365 __tablename__ = 'users_groups'
365 __tablename__ = 'users_groups'
366 __table_args__ = {'extend_existing':True}
366 __table_args__ = {'extend_existing':True}
367
367
@@ -369,7 +369,7 b' class UsersGroup(Base, BaseModel):'
369 users_group_name = Column("users_group_name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None)
369 users_group_name = Column("users_group_name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None)
370 users_group_active = Column("users_group_active", Boolean(), nullable=True, unique=None, default=None)
370 users_group_active = Column("users_group_active", Boolean(), nullable=True, unique=None, default=None)
371
371
372 members = relationship('UsersGroupMember', cascade="all, delete, delete-orphan", lazy="joined")
372 members = relationship('UserGroupMember', cascade="all, delete, delete-orphan", lazy="joined")
373
373
374 def __repr__(self):
374 def __repr__(self):
375 return '<userGroup(%s)>' % (self.users_group_name)
375 return '<userGroup(%s)>' % (self.users_group_name)
@@ -425,7 +425,7 b' class UsersGroup(Base, BaseModel):'
425 if v:
425 if v:
426 v = [v] if isinstance(v, basestring) else v
426 v = [v] if isinstance(v, basestring) else v
427 for u_id in set(v):
427 for u_id in set(v):
428 member = UsersGroupMember(users_group_id, u_id)
428 member = UserGroupMember(users_group_id, u_id)
429 members_list.append(member)
429 members_list.append(member)
430 setattr(users_group, 'members', members_list)
430 setattr(users_group, 'members', members_list)
431 setattr(users_group, k, v)
431 setattr(users_group, k, v)
@@ -442,12 +442,12 b' class UsersGroup(Base, BaseModel):'
442 try:
442 try:
443
443
444 # check if this group is not assigned to repo
444 # check if this group is not assigned to repo
445 assigned_groups = UsersGroupRepoToPerm.query()\
445 assigned_groups = UserGroupRepoToPerm.query()\
446 .filter(UsersGroupRepoToPerm.users_group_id ==
446 .filter(UserGroupRepoToPerm.users_group_id ==
447 users_group_id).all()
447 users_group_id).all()
448
448
449 if assigned_groups:
449 if assigned_groups:
450 raise UsersGroupsAssignedException('RepoGroup assigned to %s' %
450 raise UserGroupsAssignedException('RepoGroup assigned to %s' %
451 assigned_groups)
451 assigned_groups)
452
452
453 users_group = cls.get(users_group_id, cache=False)
453 users_group = cls.get(users_group_id, cache=False)
@@ -458,7 +458,7 b' class UsersGroup(Base, BaseModel):'
458 Session.rollback()
458 Session.rollback()
459 raise
459 raise
460
460
461 class UsersGroupMember(Base, BaseModel):
461 class UserGroupMember(Base, BaseModel):
462 __tablename__ = 'users_groups_members'
462 __tablename__ = 'users_groups_members'
463 __table_args__ = {'extend_existing':True}
463 __table_args__ = {'extend_existing':True}
464
464
@@ -467,7 +467,7 b' class UsersGroupMember(Base, BaseModel):'
467 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
467 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
468
468
469 user = relationship('User', lazy='joined')
469 user = relationship('User', lazy='joined')
470 users_group = relationship('UsersGroup')
470 users_group = relationship('UserGroup')
471
471
472 def __init__(self, gr_id='', u_id=''):
472 def __init__(self, gr_id='', u_id=''):
473 self.users_group_id = gr_id
473 self.users_group_id = gr_id
@@ -475,7 +475,7 b' class UsersGroupMember(Base, BaseModel):'
475
475
476 @staticmethod
476 @staticmethod
477 def add_user_to_group(group, user):
477 def add_user_to_group(group, user):
478 ugm = UsersGroupMember()
478 ugm = UserGroupMember()
479 ugm.users_group = group
479 ugm.users_group = group
480 ugm.user = user
480 ugm.user = user
481 Session.add(ugm)
481 Session.add(ugm)
@@ -505,7 +505,7 b' class Repository(Base, BaseModel):'
505 fork = relationship('Repository', remote_side=repo_id)
505 fork = relationship('Repository', remote_side=repo_id)
506 group = relationship('RepoGroup')
506 group = relationship('RepoGroup')
507 repo_to_perm = relationship('UserRepoToPerm', cascade='all', order_by='UserRepoToPerm.repo_to_perm_id')
507 repo_to_perm = relationship('UserRepoToPerm', cascade='all', order_by='UserRepoToPerm.repo_to_perm_id')
508 users_group_to_perm = relationship('UsersGroupRepoToPerm', cascade='all')
508 users_group_to_perm = relationship('UserGroupRepoToPerm', cascade='all')
509 stats = relationship('Statistics', cascade='all', uselist=False)
509 stats = relationship('Statistics', cascade='all', uselist=False)
510
510
511 followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_repo_id==Repository.repo_id', cascade='all')
511 followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_repo_id==Repository.repo_id', cascade='all')
@@ -909,7 +909,7 b' class UserToPerm(Base, BaseModel):'
909 except:
909 except:
910 Session.rollback()
910 Session.rollback()
911
911
912 class UsersGroupRepoToPerm(Base, BaseModel):
912 class UserGroupRepoToPerm(Base, BaseModel):
913 __tablename__ = 'users_group_repo_to_perm'
913 __tablename__ = 'users_group_repo_to_perm'
914 __table_args__ = (UniqueConstraint('repository_id', 'users_group_id', 'permission_id'), {'extend_existing':True})
914 __table_args__ = (UniqueConstraint('repository_id', 'users_group_id', 'permission_id'), {'extend_existing':True})
915 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
915 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
@@ -917,21 +917,21 b' class UsersGroupRepoToPerm(Base, BaseMod'
917 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
917 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
918 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
918 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
919
919
920 users_group = relationship('UsersGroup')
920 users_group = relationship('UserGroup')
921 permission = relationship('Permission')
921 permission = relationship('Permission')
922 repository = relationship('Repository')
922 repository = relationship('Repository')
923
923
924 def __repr__(self):
924 def __repr__(self):
925 return '<userGroup:%s => %s >' % (self.users_group, self.repository)
925 return '<userGroup:%s => %s >' % (self.users_group, self.repository)
926
926
927 class UsersGroupToPerm(Base, BaseModel):
927 class UserGroupToPerm(Base, BaseModel):
928 __tablename__ = 'users_group_to_perm'
928 __tablename__ = 'users_group_to_perm'
929 __table_args__ = {'extend_existing':True}
929 __table_args__ = {'extend_existing':True}
930 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
930 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
931 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
931 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
932 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
932 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
933
933
934 users_group = relationship('UsersGroup')
934 users_group = relationship('UserGroup')
935 permission = relationship('Permission')
935 permission = relationship('Permission')
936
936
937
937
@@ -305,7 +305,7 b' class User(Base, BaseModel):'
305 repo_to_perm = relationship('UserRepoToPerm', primaryjoin='UserRepoToPerm.user_id==User.user_id', cascade='all')
305 repo_to_perm = relationship('UserRepoToPerm', primaryjoin='UserRepoToPerm.user_id==User.user_id', cascade='all')
306 repo_group_to_perm = relationship('UserRepoGroupToPerm', primaryjoin='UserRepoGroupToPerm.user_id==User.user_id', cascade='all')
306 repo_group_to_perm = relationship('UserRepoGroupToPerm', primaryjoin='UserRepoGroupToPerm.user_id==User.user_id', cascade='all')
307
307
308 group_member = relationship('UsersGroupMember', cascade='all')
308 group_member = relationship('UserGroupMember', cascade='all')
309
309
310 notifications = relationship('UserNotification', cascade='all')
310 notifications = relationship('UserNotification', cascade='all')
311 # notifications assigned to this user
311 # notifications assigned to this user
@@ -423,7 +423,7 b' class UserLog(Base, BaseModel):'
423 repository = relationship('Repository', cascade='')
423 repository = relationship('Repository', cascade='')
424
424
425
425
426 class UsersGroup(Base, BaseModel):
426 class UserGroup(Base, BaseModel):
427 __tablename__ = 'users_groups'
427 __tablename__ = 'users_groups'
428 __table_args__ = (
428 __table_args__ = (
429 {'extend_existing': True, 'mysql_engine':'InnoDB',
429 {'extend_existing': True, 'mysql_engine':'InnoDB',
@@ -434,9 +434,9 b' class UsersGroup(Base, BaseModel):'
434 users_group_name = Column("users_group_name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None)
434 users_group_name = Column("users_group_name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None)
435 users_group_active = Column("users_group_active", Boolean(), nullable=True, unique=None, default=None)
435 users_group_active = Column("users_group_active", Boolean(), nullable=True, unique=None, default=None)
436
436
437 members = relationship('UsersGroupMember', cascade="all, delete, delete-orphan", lazy="joined")
437 members = relationship('UserGroupMember', cascade="all, delete, delete-orphan", lazy="joined")
438 users_group_to_perm = relationship('UsersGroupToPerm', cascade='all')
438 users_group_to_perm = relationship('UserGroupToPerm', cascade='all')
439 users_group_repo_to_perm = relationship('UsersGroupRepoToPerm', cascade='all')
439 users_group_repo_to_perm = relationship('UserGroupRepoToPerm', cascade='all')
440
440
441 def __unicode__(self):
441 def __unicode__(self):
442 return u'<userGroup(%s)>' % (self.users_group_name)
442 return u'<userGroup(%s)>' % (self.users_group_name)
@@ -465,7 +465,7 b' class UsersGroup(Base, BaseModel):'
465 return users_group.get(users_group_id)
465 return users_group.get(users_group_id)
466
466
467
467
468 class UsersGroupMember(Base, BaseModel):
468 class UserGroupMember(Base, BaseModel):
469 __tablename__ = 'users_groups_members'
469 __tablename__ = 'users_groups_members'
470 __table_args__ = (
470 __table_args__ = (
471 {'extend_existing': True, 'mysql_engine':'InnoDB',
471 {'extend_existing': True, 'mysql_engine':'InnoDB',
@@ -477,7 +477,7 b' class UsersGroupMember(Base, BaseModel):'
477 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
477 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
478
478
479 user = relationship('User', lazy='joined')
479 user = relationship('User', lazy='joined')
480 users_group = relationship('UsersGroup')
480 users_group = relationship('UserGroup')
481
481
482 def __init__(self, gr_id='', u_id=''):
482 def __init__(self, gr_id='', u_id=''):
483 self.users_group_id = gr_id
483 self.users_group_id = gr_id
@@ -510,7 +510,7 b' class Repository(Base, BaseModel):'
510 fork = relationship('Repository', remote_side=repo_id)
510 fork = relationship('Repository', remote_side=repo_id)
511 group = relationship('RepoGroup')
511 group = relationship('RepoGroup')
512 repo_to_perm = relationship('UserRepoToPerm', cascade='all', order_by='UserRepoToPerm.repo_to_perm_id')
512 repo_to_perm = relationship('UserRepoToPerm', cascade='all', order_by='UserRepoToPerm.repo_to_perm_id')
513 users_group_to_perm = relationship('UsersGroupRepoToPerm', cascade='all')
513 users_group_to_perm = relationship('UserGroupRepoToPerm', cascade='all')
514 stats = relationship('Statistics', cascade='all', uselist=False)
514 stats = relationship('Statistics', cascade='all', uselist=False)
515
515
516 followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_repo_id==Repository.repo_id', cascade='all')
516 followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_repo_id==Repository.repo_id', cascade='all')
@@ -749,7 +749,7 b' class RepoGroup(Base, BaseModel):'
749 group_description = Column("group_description", String(length=10000, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
749 group_description = Column("group_description", String(length=10000, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
750
750
751 repo_group_to_perm = relationship('UserRepoGroupToPerm', cascade='all', order_by='UserRepoGroupToPerm.group_to_perm_id')
751 repo_group_to_perm = relationship('UserRepoGroupToPerm', cascade='all', order_by='UserRepoGroupToPerm.group_to_perm_id')
752 users_group_to_perm = relationship('UsersGroupRepoGroupToPerm', cascade='all')
752 users_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all')
753
753
754 parent_group = relationship('RepoGroup', remote_side=group_id)
754 parent_group = relationship('RepoGroup', remote_side=group_id)
755
755
@@ -946,7 +946,7 b' class UserToPerm(Base, BaseModel):'
946 permission = relationship('Permission', lazy='joined')
946 permission = relationship('Permission', lazy='joined')
947
947
948
948
949 class UsersGroupRepoToPerm(Base, BaseModel):
949 class UserGroupRepoToPerm(Base, BaseModel):
950 __tablename__ = 'users_group_repo_to_perm'
950 __tablename__ = 'users_group_repo_to_perm'
951 __table_args__ = (
951 __table_args__ = (
952 UniqueConstraint('repository_id', 'users_group_id', 'permission_id'),
952 UniqueConstraint('repository_id', 'users_group_id', 'permission_id'),
@@ -958,7 +958,7 b' class UsersGroupRepoToPerm(Base, BaseMod'
958 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
958 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
959 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
959 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
960
960
961 users_group = relationship('UsersGroup')
961 users_group = relationship('UserGroup')
962 permission = relationship('Permission')
962 permission = relationship('Permission')
963 repository = relationship('Repository')
963 repository = relationship('Repository')
964
964
@@ -975,7 +975,7 b' class UsersGroupRepoToPerm(Base, BaseMod'
975 return u'<userGroup:%s => %s >' % (self.users_group, self.repository)
975 return u'<userGroup:%s => %s >' % (self.users_group, self.repository)
976
976
977
977
978 class UsersGroupToPerm(Base, BaseModel):
978 class UserGroupToPerm(Base, BaseModel):
979 __tablename__ = 'users_group_to_perm'
979 __tablename__ = 'users_group_to_perm'
980 __table_args__ = (
980 __table_args__ = (
981 UniqueConstraint('users_group_id', 'permission_id',),
981 UniqueConstraint('users_group_id', 'permission_id',),
@@ -986,7 +986,7 b' class UsersGroupToPerm(Base, BaseModel):'
986 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
986 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
987 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
987 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
988
988
989 users_group = relationship('UsersGroup')
989 users_group = relationship('UserGroup')
990 permission = relationship('Permission')
990 permission = relationship('Permission')
991
991
992
992
@@ -1008,7 +1008,7 b' class UserRepoGroupToPerm(Base, BaseMode'
1008 permission = relationship('Permission')
1008 permission = relationship('Permission')
1009
1009
1010
1010
1011 class UsersGroupRepoGroupToPerm(Base, BaseModel):
1011 class UserGroupRepoGroupToPerm(Base, BaseModel):
1012 __tablename__ = 'users_group_repo_group_to_perm'
1012 __tablename__ = 'users_group_repo_group_to_perm'
1013 __table_args__ = (
1013 __table_args__ = (
1014 UniqueConstraint('users_group_id', 'group_id'),
1014 UniqueConstraint('users_group_id', 'group_id'),
@@ -1021,7 +1021,7 b' class UsersGroupRepoGroupToPerm(Base, Ba'
1021 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
1021 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
1022 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
1022 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
1023
1023
1024 users_group = relationship('UsersGroup')
1024 users_group = relationship('UserGroup')
1025 permission = relationship('Permission')
1025 permission = relationship('Permission')
1026 group = relationship('RepoGroup')
1026 group = relationship('RepoGroup')
1027
1027
@@ -322,7 +322,7 b' class User(Base, BaseModel):'
322 repo_to_perm = relationship('UserRepoToPerm', primaryjoin='UserRepoToPerm.user_id==User.user_id', cascade='all')
322 repo_to_perm = relationship('UserRepoToPerm', primaryjoin='UserRepoToPerm.user_id==User.user_id', cascade='all')
323 repo_group_to_perm = relationship('UserRepoGroupToPerm', primaryjoin='UserRepoGroupToPerm.user_id==User.user_id', cascade='all')
323 repo_group_to_perm = relationship('UserRepoGroupToPerm', primaryjoin='UserRepoGroupToPerm.user_id==User.user_id', cascade='all')
324
324
325 group_member = relationship('UsersGroupMember', cascade='all')
325 group_member = relationship('UserGroupMember', cascade='all')
326
326
327 notifications = relationship('UserNotification', cascade='all')
327 notifications = relationship('UserNotification', cascade='all')
328 # notifications assigned to this user
328 # notifications assigned to this user
@@ -521,7 +521,7 b' class UserLog(Base, BaseModel):'
521 repository = relationship('Repository', cascade='')
521 repository = relationship('Repository', cascade='')
522
522
523
523
524 class UsersGroup(Base, BaseModel):
524 class UserGroup(Base, BaseModel):
525 __tablename__ = 'users_groups'
525 __tablename__ = 'users_groups'
526 __table_args__ = (
526 __table_args__ = (
527 {'extend_existing': True, 'mysql_engine': 'InnoDB',
527 {'extend_existing': True, 'mysql_engine': 'InnoDB',
@@ -533,9 +533,9 b' class UsersGroup(Base, BaseModel):'
533 users_group_active = Column("users_group_active", Boolean(), nullable=True, unique=None, default=None)
533 users_group_active = Column("users_group_active", Boolean(), nullable=True, unique=None, default=None)
534 inherit_default_permissions = Column("users_group_inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
534 inherit_default_permissions = Column("users_group_inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
535
535
536 members = relationship('UsersGroupMember', cascade="all, delete, delete-orphan", lazy="joined")
536 members = relationship('UserGroupMember', cascade="all, delete, delete-orphan", lazy="joined")
537 users_group_to_perm = relationship('UsersGroupToPerm', cascade='all')
537 users_group_to_perm = relationship('UserGroupToPerm', cascade='all')
538 users_group_repo_to_perm = relationship('UsersGroupRepoToPerm', cascade='all')
538 users_group_repo_to_perm = relationship('UserGroupRepoToPerm', cascade='all')
539
539
540 def __unicode__(self):
540 def __unicode__(self):
541 return u'<userGroup(%s)>' % (self.users_group_name)
541 return u'<userGroup(%s)>' % (self.users_group_name)
@@ -575,7 +575,7 b' class UsersGroup(Base, BaseModel):'
575 return data
575 return data
576
576
577
577
578 class UsersGroupMember(Base, BaseModel):
578 class UserGroupMember(Base, BaseModel):
579 __tablename__ = 'users_groups_members'
579 __tablename__ = 'users_groups_members'
580 __table_args__ = (
580 __table_args__ = (
581 {'extend_existing': True, 'mysql_engine': 'InnoDB',
581 {'extend_existing': True, 'mysql_engine': 'InnoDB',
@@ -587,7 +587,7 b' class UsersGroupMember(Base, BaseModel):'
587 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
587 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
588
588
589 user = relationship('User', lazy='joined')
589 user = relationship('User', lazy='joined')
590 users_group = relationship('UsersGroup')
590 users_group = relationship('UserGroup')
591
591
592 def __init__(self, gr_id='', u_id=''):
592 def __init__(self, gr_id='', u_id=''):
593 self.users_group_id = gr_id
593 self.users_group_id = gr_id
@@ -625,7 +625,7 b' class Repository(Base, BaseModel):'
625 fork = relationship('Repository', remote_side=repo_id)
625 fork = relationship('Repository', remote_side=repo_id)
626 group = relationship('RepoGroup')
626 group = relationship('RepoGroup')
627 repo_to_perm = relationship('UserRepoToPerm', cascade='all', order_by='UserRepoToPerm.repo_to_perm_id')
627 repo_to_perm = relationship('UserRepoToPerm', cascade='all', order_by='UserRepoToPerm.repo_to_perm_id')
628 users_group_to_perm = relationship('UsersGroupRepoToPerm', cascade='all')
628 users_group_to_perm = relationship('UserGroupRepoToPerm', cascade='all')
629 stats = relationship('Statistics', cascade='all', uselist=False)
629 stats = relationship('Statistics', cascade='all', uselist=False)
630
630
631 followers = relationship('UserFollowing',
631 followers = relationship('UserFollowing',
@@ -1013,7 +1013,7 b' class RepoGroup(Base, BaseModel):'
1013 enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
1013 enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
1014
1014
1015 repo_group_to_perm = relationship('UserRepoGroupToPerm', cascade='all', order_by='UserRepoGroupToPerm.group_to_perm_id')
1015 repo_group_to_perm = relationship('UserRepoGroupToPerm', cascade='all', order_by='UserRepoGroupToPerm.group_to_perm_id')
1016 users_group_to_perm = relationship('UsersGroupRepoGroupToPerm', cascade='all')
1016 users_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all')
1017
1017
1018 parent_group = relationship('RepoGroup', remote_side=group_id)
1018 parent_group = relationship('RepoGroup', remote_side=group_id)
1019
1019
@@ -1277,7 +1277,7 b' class UserToPerm(Base, BaseModel):'
1277 permission = relationship('Permission', lazy='joined')
1277 permission = relationship('Permission', lazy='joined')
1278
1278
1279
1279
1280 class UsersGroupRepoToPerm(Base, BaseModel):
1280 class UserGroupRepoToPerm(Base, BaseModel):
1281 __tablename__ = 'users_group_repo_to_perm'
1281 __tablename__ = 'users_group_repo_to_perm'
1282 __table_args__ = (
1282 __table_args__ = (
1283 UniqueConstraint('repository_id', 'users_group_id', 'permission_id'),
1283 UniqueConstraint('repository_id', 'users_group_id', 'permission_id'),
@@ -1289,7 +1289,7 b' class UsersGroupRepoToPerm(Base, BaseMod'
1289 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
1289 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
1290 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
1290 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
1291
1291
1292 users_group = relationship('UsersGroup')
1292 users_group = relationship('UserGroup')
1293 permission = relationship('Permission')
1293 permission = relationship('Permission')
1294 repository = relationship('Repository')
1294 repository = relationship('Repository')
1295
1295
@@ -1306,7 +1306,7 b' class UsersGroupRepoToPerm(Base, BaseMod'
1306 return u'<userGroup:%s => %s >' % (self.users_group, self.repository)
1306 return u'<userGroup:%s => %s >' % (self.users_group, self.repository)
1307
1307
1308
1308
1309 class UsersGroupToPerm(Base, BaseModel):
1309 class UserGroupToPerm(Base, BaseModel):
1310 __tablename__ = 'users_group_to_perm'
1310 __tablename__ = 'users_group_to_perm'
1311 __table_args__ = (
1311 __table_args__ = (
1312 UniqueConstraint('users_group_id', 'permission_id',),
1312 UniqueConstraint('users_group_id', 'permission_id',),
@@ -1317,7 +1317,7 b' class UsersGroupToPerm(Base, BaseModel):'
1317 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
1317 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
1318 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
1318 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
1319
1319
1320 users_group = relationship('UsersGroup')
1320 users_group = relationship('UserGroup')
1321 permission = relationship('Permission')
1321 permission = relationship('Permission')
1322
1322
1323
1323
@@ -1339,7 +1339,7 b' class UserRepoGroupToPerm(Base, BaseMode'
1339 permission = relationship('Permission')
1339 permission = relationship('Permission')
1340
1340
1341
1341
1342 class UsersGroupRepoGroupToPerm(Base, BaseModel):
1342 class UserGroupRepoGroupToPerm(Base, BaseModel):
1343 __tablename__ = 'users_group_repo_group_to_perm'
1343 __tablename__ = 'users_group_repo_group_to_perm'
1344 __table_args__ = (
1344 __table_args__ = (
1345 UniqueConstraint('users_group_id', 'group_id'),
1345 UniqueConstraint('users_group_id', 'group_id'),
@@ -1352,7 +1352,7 b' class UsersGroupRepoGroupToPerm(Base, Ba'
1352 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
1352 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
1353 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
1353 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
1354
1354
1355 users_group = relationship('UsersGroup')
1355 users_group = relationship('UserGroup')
1356 permission = relationship('Permission')
1356 permission = relationship('Permission')
1357 group = relationship('RepoGroup')
1357 group = relationship('RepoGroup')
1358
1358
@@ -341,7 +341,7 b' class User(Base, BaseModel):'
341 repo_to_perm = relationship('UserRepoToPerm', primaryjoin='UserRepoToPerm.user_id==User.user_id', cascade='all')
341 repo_to_perm = relationship('UserRepoToPerm', primaryjoin='UserRepoToPerm.user_id==User.user_id', cascade='all')
342 repo_group_to_perm = relationship('UserRepoGroupToPerm', primaryjoin='UserRepoGroupToPerm.user_id==User.user_id', cascade='all')
342 repo_group_to_perm = relationship('UserRepoGroupToPerm', primaryjoin='UserRepoGroupToPerm.user_id==User.user_id', cascade='all')
343
343
344 group_member = relationship('UsersGroupMember', cascade='all')
344 group_member = relationship('UserGroupMember', cascade='all')
345
345
346 notifications = relationship('UserNotification', cascade='all')
346 notifications = relationship('UserNotification', cascade='all')
347 # notifications assigned to this user
347 # notifications assigned to this user
@@ -541,7 +541,7 b' class UserLog(Base, BaseModel):'
541 repository = relationship('Repository', cascade='')
541 repository = relationship('Repository', cascade='')
542
542
543
543
544 class UsersGroup(Base, BaseModel):
544 class UserGroup(Base, BaseModel):
545 __tablename__ = 'users_groups'
545 __tablename__ = 'users_groups'
546 __table_args__ = (
546 __table_args__ = (
547 {'extend_existing': True, 'mysql_engine': 'InnoDB',
547 {'extend_existing': True, 'mysql_engine': 'InnoDB',
@@ -553,9 +553,9 b' class UsersGroup(Base, BaseModel):'
553 users_group_active = Column("users_group_active", Boolean(), nullable=True, unique=None, default=None)
553 users_group_active = Column("users_group_active", Boolean(), nullable=True, unique=None, default=None)
554 inherit_default_permissions = Column("users_group_inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
554 inherit_default_permissions = Column("users_group_inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
555
555
556 members = relationship('UsersGroupMember', cascade="all, delete, delete-orphan", lazy="joined")
556 members = relationship('UserGroupMember', cascade="all, delete, delete-orphan", lazy="joined")
557 users_group_to_perm = relationship('UsersGroupToPerm', cascade='all')
557 users_group_to_perm = relationship('UserGroupToPerm', cascade='all')
558 users_group_repo_to_perm = relationship('UsersGroupRepoToPerm', cascade='all')
558 users_group_repo_to_perm = relationship('UserGroupRepoToPerm', cascade='all')
559
559
560 def __unicode__(self):
560 def __unicode__(self):
561 return u'<userGroup(%s)>' % (self.users_group_name)
561 return u'<userGroup(%s)>' % (self.users_group_name)
@@ -595,7 +595,7 b' class UsersGroup(Base, BaseModel):'
595 return data
595 return data
596
596
597
597
598 class UsersGroupMember(Base, BaseModel):
598 class UserGroupMember(Base, BaseModel):
599 __tablename__ = 'users_groups_members'
599 __tablename__ = 'users_groups_members'
600 __table_args__ = (
600 __table_args__ = (
601 {'extend_existing': True, 'mysql_engine': 'InnoDB',
601 {'extend_existing': True, 'mysql_engine': 'InnoDB',
@@ -607,7 +607,7 b' class UsersGroupMember(Base, BaseModel):'
607 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
607 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
608
608
609 user = relationship('User', lazy='joined')
609 user = relationship('User', lazy='joined')
610 users_group = relationship('UsersGroup')
610 users_group = relationship('UserGroup')
611
611
612 def __init__(self, gr_id='', u_id=''):
612 def __init__(self, gr_id='', u_id=''):
613 self.users_group_id = gr_id
613 self.users_group_id = gr_id
@@ -645,7 +645,7 b' class Repository(Base, BaseModel):'
645 fork = relationship('Repository', remote_side=repo_id)
645 fork = relationship('Repository', remote_side=repo_id)
646 group = relationship('RepoGroup')
646 group = relationship('RepoGroup')
647 repo_to_perm = relationship('UserRepoToPerm', cascade='all', order_by='UserRepoToPerm.repo_to_perm_id')
647 repo_to_perm = relationship('UserRepoToPerm', cascade='all', order_by='UserRepoToPerm.repo_to_perm_id')
648 users_group_to_perm = relationship('UsersGroupRepoToPerm', cascade='all')
648 users_group_to_perm = relationship('UserGroupRepoToPerm', cascade='all')
649 stats = relationship('Statistics', cascade='all', uselist=False)
649 stats = relationship('Statistics', cascade='all', uselist=False)
650
650
651 followers = relationship('UserFollowing',
651 followers = relationship('UserFollowing',
@@ -1033,7 +1033,7 b' class RepoGroup(Base, BaseModel):'
1033 enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
1033 enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
1034
1034
1035 repo_group_to_perm = relationship('UserRepoGroupToPerm', cascade='all', order_by='UserRepoGroupToPerm.group_to_perm_id')
1035 repo_group_to_perm = relationship('UserRepoGroupToPerm', cascade='all', order_by='UserRepoGroupToPerm.group_to_perm_id')
1036 users_group_to_perm = relationship('UsersGroupRepoGroupToPerm', cascade='all')
1036 users_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all')
1037
1037
1038 parent_group = relationship('RepoGroup', remote_side=group_id)
1038 parent_group = relationship('RepoGroup', remote_side=group_id)
1039
1039
@@ -1297,7 +1297,7 b' class UserToPerm(Base, BaseModel):'
1297 permission = relationship('Permission', lazy='joined')
1297 permission = relationship('Permission', lazy='joined')
1298
1298
1299
1299
1300 class UsersGroupRepoToPerm(Base, BaseModel):
1300 class UserGroupRepoToPerm(Base, BaseModel):
1301 __tablename__ = 'users_group_repo_to_perm'
1301 __tablename__ = 'users_group_repo_to_perm'
1302 __table_args__ = (
1302 __table_args__ = (
1303 UniqueConstraint('repository_id', 'users_group_id', 'permission_id'),
1303 UniqueConstraint('repository_id', 'users_group_id', 'permission_id'),
@@ -1309,7 +1309,7 b' class UsersGroupRepoToPerm(Base, BaseMod'
1309 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
1309 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
1310 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
1310 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
1311
1311
1312 users_group = relationship('UsersGroup')
1312 users_group = relationship('UserGroup')
1313 permission = relationship('Permission')
1313 permission = relationship('Permission')
1314 repository = relationship('Repository')
1314 repository = relationship('Repository')
1315
1315
@@ -1326,7 +1326,7 b' class UsersGroupRepoToPerm(Base, BaseMod'
1326 return u'<userGroup:%s => %s >' % (self.users_group, self.repository)
1326 return u'<userGroup:%s => %s >' % (self.users_group, self.repository)
1327
1327
1328
1328
1329 class UsersGroupToPerm(Base, BaseModel):
1329 class UserGroupToPerm(Base, BaseModel):
1330 __tablename__ = 'users_group_to_perm'
1330 __tablename__ = 'users_group_to_perm'
1331 __table_args__ = (
1331 __table_args__ = (
1332 UniqueConstraint('users_group_id', 'permission_id',),
1332 UniqueConstraint('users_group_id', 'permission_id',),
@@ -1337,7 +1337,7 b' class UsersGroupToPerm(Base, BaseModel):'
1337 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
1337 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
1338 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
1338 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
1339
1339
1340 users_group = relationship('UsersGroup')
1340 users_group = relationship('UserGroup')
1341 permission = relationship('Permission')
1341 permission = relationship('Permission')
1342
1342
1343
1343
@@ -1359,7 +1359,7 b' class UserRepoGroupToPerm(Base, BaseMode'
1359 permission = relationship('Permission')
1359 permission = relationship('Permission')
1360
1360
1361
1361
1362 class UsersGroupRepoGroupToPerm(Base, BaseModel):
1362 class UserGroupRepoGroupToPerm(Base, BaseModel):
1363 __tablename__ = 'users_group_repo_group_to_perm'
1363 __tablename__ = 'users_group_repo_group_to_perm'
1364 __table_args__ = (
1364 __table_args__ = (
1365 UniqueConstraint('users_group_id', 'group_id'),
1365 UniqueConstraint('users_group_id', 'group_id'),
@@ -1372,7 +1372,7 b' class UsersGroupRepoGroupToPerm(Base, Ba'
1372 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
1372 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
1373 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
1373 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
1374
1374
1375 users_group = relationship('UsersGroup')
1375 users_group = relationship('UserGroup')
1376 permission = relationship('Permission')
1376 permission = relationship('Permission')
1377 group = relationship('RepoGroup')
1377 group = relationship('RepoGroup')
1378
1378
@@ -341,7 +341,7 b' class User(Base, BaseModel):'
341 repo_to_perm = relationship('UserRepoToPerm', primaryjoin='UserRepoToPerm.user_id==User.user_id', cascade='all')
341 repo_to_perm = relationship('UserRepoToPerm', primaryjoin='UserRepoToPerm.user_id==User.user_id', cascade='all')
342 repo_group_to_perm = relationship('UserRepoGroupToPerm', primaryjoin='UserRepoGroupToPerm.user_id==User.user_id', cascade='all')
342 repo_group_to_perm = relationship('UserRepoGroupToPerm', primaryjoin='UserRepoGroupToPerm.user_id==User.user_id', cascade='all')
343
343
344 group_member = relationship('UsersGroupMember', cascade='all')
344 group_member = relationship('UserGroupMember', cascade='all')
345
345
346 notifications = relationship('UserNotification', cascade='all')
346 notifications = relationship('UserNotification', cascade='all')
347 # notifications assigned to this user
347 # notifications assigned to this user
@@ -575,7 +575,7 b' class UserLog(Base, BaseModel):'
575 repository = relationship('Repository', cascade='')
575 repository = relationship('Repository', cascade='')
576
576
577
577
578 class UsersGroup(Base, BaseModel):
578 class UserGroup(Base, BaseModel):
579 __tablename__ = 'users_groups'
579 __tablename__ = 'users_groups'
580 __table_args__ = (
580 __table_args__ = (
581 {'extend_existing': True, 'mysql_engine': 'InnoDB',
581 {'extend_existing': True, 'mysql_engine': 'InnoDB',
@@ -587,9 +587,9 b' class UsersGroup(Base, BaseModel):'
587 users_group_active = Column("users_group_active", Boolean(), nullable=True, unique=None, default=None)
587 users_group_active = Column("users_group_active", Boolean(), nullable=True, unique=None, default=None)
588 inherit_default_permissions = Column("users_group_inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
588 inherit_default_permissions = Column("users_group_inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
589
589
590 members = relationship('UsersGroupMember', cascade="all, delete, delete-orphan", lazy="joined")
590 members = relationship('UserGroupMember', cascade="all, delete, delete-orphan", lazy="joined")
591 users_group_to_perm = relationship('UsersGroupToPerm', cascade='all')
591 users_group_to_perm = relationship('UserGroupToPerm', cascade='all')
592 users_group_repo_to_perm = relationship('UsersGroupRepoToPerm', cascade='all')
592 users_group_repo_to_perm = relationship('UserGroupRepoToPerm', cascade='all')
593
593
594 def __unicode__(self):
594 def __unicode__(self):
595 return u'<userGroup(%s)>' % (self.users_group_name)
595 return u'<userGroup(%s)>' % (self.users_group_name)
@@ -629,7 +629,7 b' class UsersGroup(Base, BaseModel):'
629 return data
629 return data
630
630
631
631
632 class UsersGroupMember(Base, BaseModel):
632 class UserGroupMember(Base, BaseModel):
633 __tablename__ = 'users_groups_members'
633 __tablename__ = 'users_groups_members'
634 __table_args__ = (
634 __table_args__ = (
635 {'extend_existing': True, 'mysql_engine': 'InnoDB',
635 {'extend_existing': True, 'mysql_engine': 'InnoDB',
@@ -641,7 +641,7 b' class UsersGroupMember(Base, BaseModel):'
641 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
641 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
642
642
643 user = relationship('User', lazy='joined')
643 user = relationship('User', lazy='joined')
644 users_group = relationship('UsersGroup')
644 users_group = relationship('UserGroup')
645
645
646 def __init__(self, gr_id='', u_id=''):
646 def __init__(self, gr_id='', u_id=''):
647 self.users_group_id = gr_id
647 self.users_group_id = gr_id
@@ -680,7 +680,7 b' class Repository(Base, BaseModel):'
680 fork = relationship('Repository', remote_side=repo_id)
680 fork = relationship('Repository', remote_side=repo_id)
681 group = relationship('RepoGroup')
681 group = relationship('RepoGroup')
682 repo_to_perm = relationship('UserRepoToPerm', cascade='all', order_by='UserRepoToPerm.repo_to_perm_id')
682 repo_to_perm = relationship('UserRepoToPerm', cascade='all', order_by='UserRepoToPerm.repo_to_perm_id')
683 users_group_to_perm = relationship('UsersGroupRepoToPerm', cascade='all')
683 users_group_to_perm = relationship('UserGroupRepoToPerm', cascade='all')
684 stats = relationship('Statistics', cascade='all', uselist=False)
684 stats = relationship('Statistics', cascade='all', uselist=False)
685
685
686 followers = relationship('UserFollowing',
686 followers = relationship('UserFollowing',
@@ -1139,7 +1139,7 b' class RepoGroup(Base, BaseModel):'
1139 enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
1139 enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
1140
1140
1141 repo_group_to_perm = relationship('UserRepoGroupToPerm', cascade='all', order_by='UserRepoGroupToPerm.group_to_perm_id')
1141 repo_group_to_perm = relationship('UserRepoGroupToPerm', cascade='all', order_by='UserRepoGroupToPerm.group_to_perm_id')
1142 users_group_to_perm = relationship('UsersGroupRepoGroupToPerm', cascade='all')
1142 users_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all')
1143
1143
1144 parent_group = relationship('RepoGroup', remote_side=group_id)
1144 parent_group = relationship('RepoGroup', remote_side=group_id)
1145
1145
@@ -1403,7 +1403,7 b' class UserToPerm(Base, BaseModel):'
1403 permission = relationship('Permission', lazy='joined')
1403 permission = relationship('Permission', lazy='joined')
1404
1404
1405
1405
1406 class UsersGroupRepoToPerm(Base, BaseModel):
1406 class UserGroupRepoToPerm(Base, BaseModel):
1407 __tablename__ = 'users_group_repo_to_perm'
1407 __tablename__ = 'users_group_repo_to_perm'
1408 __table_args__ = (
1408 __table_args__ = (
1409 UniqueConstraint('repository_id', 'users_group_id', 'permission_id'),
1409 UniqueConstraint('repository_id', 'users_group_id', 'permission_id'),
@@ -1415,7 +1415,7 b' class UsersGroupRepoToPerm(Base, BaseMod'
1415 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
1415 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
1416 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
1416 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
1417
1417
1418 users_group = relationship('UsersGroup')
1418 users_group = relationship('UserGroup')
1419 permission = relationship('Permission')
1419 permission = relationship('Permission')
1420 repository = relationship('Repository')
1420 repository = relationship('Repository')
1421
1421
@@ -1432,7 +1432,7 b' class UsersGroupRepoToPerm(Base, BaseMod'
1432 return u'<userGroup:%s => %s >' % (self.users_group, self.repository)
1432 return u'<userGroup:%s => %s >' % (self.users_group, self.repository)
1433
1433
1434
1434
1435 class UsersGroupToPerm(Base, BaseModel):
1435 class UserGroupToPerm(Base, BaseModel):
1436 __tablename__ = 'users_group_to_perm'
1436 __tablename__ = 'users_group_to_perm'
1437 __table_args__ = (
1437 __table_args__ = (
1438 UniqueConstraint('users_group_id', 'permission_id',),
1438 UniqueConstraint('users_group_id', 'permission_id',),
@@ -1443,7 +1443,7 b' class UsersGroupToPerm(Base, BaseModel):'
1443 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
1443 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
1444 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
1444 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
1445
1445
1446 users_group = relationship('UsersGroup')
1446 users_group = relationship('UserGroup')
1447 permission = relationship('Permission')
1447 permission = relationship('Permission')
1448
1448
1449
1449
@@ -1465,7 +1465,7 b' class UserRepoGroupToPerm(Base, BaseMode'
1465 permission = relationship('Permission')
1465 permission = relationship('Permission')
1466
1466
1467
1467
1468 class UsersGroupRepoGroupToPerm(Base, BaseModel):
1468 class UserGroupRepoGroupToPerm(Base, BaseModel):
1469 __tablename__ = 'users_group_repo_group_to_perm'
1469 __tablename__ = 'users_group_repo_group_to_perm'
1470 __table_args__ = (
1470 __table_args__ = (
1471 UniqueConstraint('users_group_id', 'group_id'),
1471 UniqueConstraint('users_group_id', 'group_id'),
@@ -1478,7 +1478,7 b' class UsersGroupRepoGroupToPerm(Base, Ba'
1478 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
1478 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
1479 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
1479 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
1480
1480
1481 users_group = relationship('UsersGroup')
1481 users_group = relationship('UserGroup')
1482 permission = relationship('Permission')
1482 permission = relationship('Permission')
1483 group = relationship('RepoGroup')
1483 group = relationship('RepoGroup')
1484
1484
@@ -34,26 +34,26 b' def upgrade(migrate_engine):'
34 #==========================================================================
34 #==========================================================================
35 # Add table `users_groups`
35 # Add table `users_groups`
36 #==========================================================================
36 #==========================================================================
37 from rhodecode.lib.dbmigrate.schema.db_1_2_0 import UsersGroup
37 from rhodecode.lib.dbmigrate.schema.db_1_2_0 import UserGroup
38 UsersGroup().__table__.create()
38 UserGroup().__table__.create()
39
39
40 #==========================================================================
40 #==========================================================================
41 # Add table `users_groups_members`
41 # Add table `users_groups_members`
42 #==========================================================================
42 #==========================================================================
43 from rhodecode.lib.dbmigrate.schema.db_1_2_0 import UsersGroupMember
43 from rhodecode.lib.dbmigrate.schema.db_1_2_0 import UserGroupMember
44 UsersGroupMember().__table__.create()
44 UserGroupMember().__table__.create()
45
45
46 #==========================================================================
46 #==========================================================================
47 # Add table `users_group_repo_to_perm`
47 # Add table `users_group_repo_to_perm`
48 #==========================================================================
48 #==========================================================================
49 from rhodecode.lib.dbmigrate.schema.db_1_2_0 import UsersGroupRepoToPerm
49 from rhodecode.lib.dbmigrate.schema.db_1_2_0 import UserGroupRepoToPerm
50 UsersGroupRepoToPerm().__table__.create()
50 UserGroupRepoToPerm().__table__.create()
51
51
52 #==========================================================================
52 #==========================================================================
53 # Add table `users_group_to_perm`
53 # Add table `users_group_to_perm`
54 #==========================================================================
54 #==========================================================================
55 from rhodecode.lib.dbmigrate.schema.db_1_2_0 import UsersGroupToPerm
55 from rhodecode.lib.dbmigrate.schema.db_1_2_0 import UserGroupToPerm
56 UsersGroupToPerm().__table__.create()
56 UserGroupToPerm().__table__.create()
57
57
58 #==========================================================================
58 #==========================================================================
59 # Upgrade of `users` table
59 # Upgrade of `users` table
@@ -21,8 +21,8 b' def upgrade(migrate_engine):'
21 #==========================================================================
21 #==========================================================================
22 # Add table `users_group_repo_group_to_perm`
22 # Add table `users_group_repo_group_to_perm`
23 #==========================================================================
23 #==========================================================================
24 from rhodecode.lib.dbmigrate.schema.db_1_3_0 import UsersGroupRepoGroupToPerm
24 from rhodecode.lib.dbmigrate.schema.db_1_3_0 import UserGroupRepoGroupToPerm
25 UsersGroupRepoGroupToPerm().__table__.create()
25 UserGroupRepoGroupToPerm().__table__.create()
26
26
27 #==========================================================================
27 #==========================================================================
28 # Add table `changeset_comments`
28 # Add table `changeset_comments`
@@ -45,8 +45,8 b' def upgrade(migrate_engine):'
45 #==========================================================================
45 #==========================================================================
46 # Add unique to table `users_group_to_perm`
46 # Add unique to table `users_group_to_perm`
47 #==========================================================================
47 #==========================================================================
48 from rhodecode.lib.dbmigrate.schema.db_1_3_0 import UsersGroupToPerm
48 from rhodecode.lib.dbmigrate.schema.db_1_3_0 import UserGroupToPerm
49 tbl = UsersGroupToPerm().__table__
49 tbl = UserGroupToPerm().__table__
50 cons = UniqueConstraint('users_group_id', 'permission_id', table=tbl)
50 cons = UniqueConstraint('users_group_id', 'permission_id', table=tbl)
51 cons.create()
51 cons.create()
52
52
@@ -74,8 +74,8 b' def upgrade(migrate_engine):'
74 #==========================================================================
74 #==========================================================================
75 # USERS GROUP TABLE
75 # USERS GROUP TABLE
76 #==========================================================================
76 #==========================================================================
77 from rhodecode.lib.dbmigrate.schema.db_1_3_0 import UsersGroup
77 from rhodecode.lib.dbmigrate.schema.db_1_3_0 import UserGroup
78 tbl = UsersGroup.__table__
78 tbl = UserGroup.__table__
79 # add inherit_default_permission column
79 # add inherit_default_permission column
80 gr_inherit_default_permissions = Column(
80 gr_inherit_default_permissions = Column(
81 "users_group_inherit_default_permissions",
81 "users_group_inherit_default_permissions",
@@ -50,7 +50,7 b' class UserOwnsReposException(Exception):'
50 pass
50 pass
51
51
52
52
53 class UsersGroupsAssignedException(Exception):
53 class UserGroupsAssignedException(Exception):
54 pass
54 pass
55
55
56
56
@@ -684,9 +684,9 b' def action_parser(user_log, feed=False, '
684 get_user_name, 'user_add.png'),
684 get_user_name, 'user_add.png'),
685 'admin_updated_user': (_('[updated] user'),
685 'admin_updated_user': (_('[updated] user'),
686 get_user_name, 'user_edit.png'),
686 get_user_name, 'user_edit.png'),
687 'admin_created_users_group': (_('[created] users group'),
687 'admin_created_users_group': (_('[created] user group'),
688 get_users_group, 'group_add.png'),
688 get_users_group, 'group_add.png'),
689 'admin_updated_users_group': (_('[updated] users group'),
689 'admin_updated_users_group': (_('[updated] user group'),
690 get_users_group, 'group_edit.png'),
690 get_users_group, 'group_edit.png'),
691 'user_commented_revision': (_('[commented] on revision in repository'),
691 'user_commented_revision': (_('[commented] on revision in repository'),
692 get_cs_links, 'comment_add.png'),
692 get_cs_links, 'comment_add.png'),
@@ -977,7 +977,7 b' def fancy_file_stats(stats):'
977 return literal('<div style="width:%spx">%s%s</div>' % (width, d_a, d_d))
977 return literal('<div style="width:%spx">%s%s</div>' % (width, d_a, d_d))
978
978
979
979
980 def urlify_text(text_):
980 def urlify_text(text_, safe=True):
981 """
981 """
982 Extrac urls from text and make html links out of them
982 Extrac urls from text and make html links out of them
983
983
@@ -990,8 +990,10 b' def urlify_text(text_):'
990 def url_func(match_obj):
990 def url_func(match_obj):
991 url_full = match_obj.groups()[0]
991 url_full = match_obj.groups()[0]
992 return '<a href="%(url)s">%(url)s</a>' % ({'url': url_full})
992 return '<a href="%(url)s">%(url)s</a>' % ({'url': url_full})
993
993 _newtext = url_pat.sub(url_func, text_)
994 return literal(url_pat.sub(url_func, text_))
994 if safe:
995 return literal(_newtext)
996 return _newtext
995
997
996
998
997 def urlify_changesets(text_, repository):
999 def urlify_changesets(text_, repository):
@@ -1002,21 +1004,16 b' def urlify_changesets(text_, repository)'
1002 :param repository: repo name to build the URL with
1004 :param repository: repo name to build the URL with
1003 """
1005 """
1004 from pylons import url # doh, we need to re-import url to mock it later
1006 from pylons import url # doh, we need to re-import url to mock it later
1005 URL_PAT = re.compile(r'(?:^|\s)([0-9a-fA-F]{12,40})(?:$|\s)')
1007 URL_PAT = re.compile(r'(^|\s)([0-9a-fA-F]{12,40})($|\s)')
1006
1008
1007 def url_func(match_obj):
1009 def url_func(match_obj):
1008 rev = match_obj.groups()[0]
1010 rev = match_obj.groups()[1]
1009 pref = ''
1011 pref = match_obj.groups()[0]
1010 suf = ''
1012 suf = match_obj.groups()[2]
1011 if match_obj.group().startswith(' '):
1013
1012 pref = ' '
1013 if match_obj.group().endswith(' '):
1014 suf = ' '
1015 tmpl = (
1014 tmpl = (
1016 '%(pref)s<a class="%(cls)s" href="%(url)s">'
1015 '%(pref)s<a class="%(cls)s" href="%(url)s">'
1017 '%(rev)s'
1016 '%(rev)s</a>%(suf)s'
1018 '</a>'
1019 '%(suf)s'
1020 )
1017 )
1021 return tmpl % {
1018 return tmpl % {
1022 'pref': pref,
1019 'pref': pref,
@@ -1062,7 +1059,7 b' def urlify_commit(text_, repository=None'
1062 newtext = urlify_changesets(escaper(text_), repository)
1059 newtext = urlify_changesets(escaper(text_), repository)
1063
1060
1064 # extract http/https links and make them real urls
1061 # extract http/https links and make them real urls
1065 newtext = urlify_text(newtext)
1062 newtext = urlify_text(newtext, safe=False)
1066
1063
1067 try:
1064 try:
1068 from rhodecode import CONFIG
1065 from rhodecode import CONFIG
@@ -1,17 +1,20 b''
1 # unionrepo.py - repository class for viewing union of repositories
1 # unionrepo.py - repository class for viewing union of repository changesets
2 #
2 #
3 # Derived from Mercurial 2.5 bundlerepo.py
3 # Derived from bundlerepo.py
4 # Copyright 2006, 2007 Benoit Boissinot <bboissin@gmail.com>
4 # Copyright 2006, 2007 Benoit Boissinot <bboissin@gmail.com>
5 # Copyright 2013 Unity Technologies, Mads Kiilerich <madski@unity3d.com>
5 # Copyright 2013 Unity Technologies, Mads Kiilerich <madski@unity3d.com>
6 #
6 #
7 # This software may be used and distributed according to the terms of the
7 # This software may be used and distributed according to the terms of the
8 # GNU General Public License version 2 or any later version.
8 # GNU General Public License version 2 or any later version.
9
9
10 """Repository class for in-memory pull of one local repository to another.
10 """Repository class for "in-memory pull" of one local repository to another,
11 allowing operations like diff and log with revsets.
11 """
12 """
12
13
14 import os
13 from mercurial.node import nullid
15 from mercurial.node import nullid
14 from mercurial import util, mdiff
16 from mercurial.i18n import _
17 from mercurial import util, mdiff, cmdutil, scmutil
15 from mercurial import localrepo, changelog, manifest, filelog, revlog
18 from mercurial import localrepo, changelog, manifest, filelog, revlog
16
19
17 class unionrevlog(revlog.revlog):
20 class unionrevlog(revlog.revlog):
@@ -20,15 +23,14 b' class unionrevlog(revlog.revlog):'
20 # To retrieve a revision, we just need to know the node id so we can
23 # To retrieve a revision, we just need to know the node id so we can
21 # look it up in revlog2.
24 # look it up in revlog2.
22 #
25 #
23 # basemap is indexed with revisions coming from the second revlog.
24 #
25 # To differentiate a rev in the second revlog from a rev in the revlog,
26 # To differentiate a rev in the second revlog from a rev in the revlog,
26 # we check revision against basemap.
27 # we check revision against repotiprev.
28 opener = scmutil.readonlyvfs(opener)
27 revlog.revlog.__init__(self, opener, indexfile)
29 revlog.revlog.__init__(self, opener, indexfile)
28 self.revlog2 = revlog2
30 self.revlog2 = revlog2
29
31
30 self.basemap = {} # mapping rev that is in revlog2 to ... nothing
31 n = len(self)
32 n = len(self)
33 self.repotiprev = n - 1
32 self.bundlerevs = set() # used by 'bundle()' revset expression
34 self.bundlerevs = set() # used by 'bundle()' revset expression
33 for rev2 in self.revlog2:
35 for rev2 in self.revlog2:
34 rev = self.revlog2.index[rev2]
36 rev = self.revlog2.index[rev2]
@@ -42,7 +44,7 b' class unionrevlog(revlog.revlog):'
42 link = linkmapper(linkrev)
44 link = linkmapper(linkrev)
43
45
44 if node in self.nodemap:
46 if node in self.nodemap:
45 # this happens for for the common revlog revisions
47 # this happens for the common revlog revisions
46 self.bundlerevs.add(self.nodemap[node])
48 self.bundlerevs.add(self.nodemap[node])
47 continue
49 continue
48
50
@@ -51,24 +53,23 b' class unionrevlog(revlog.revlog):'
51
53
52 e = (None, None, None, None,
54 e = (None, None, None, None,
53 link, self.rev(p1node), self.rev(p2node), node)
55 link, self.rev(p1node), self.rev(p2node), node)
54 self.basemap[n] = None
55 self.index.insert(-1, e)
56 self.index.insert(-1, e)
56 self.nodemap[node] = n
57 self.nodemap[node] = n
57 self.bundlerevs.add(n)
58 self.bundlerevs.add(n)
58 n += 1
59 n += 1
59
60
60 def _chunk(self, rev):
61 def _chunk(self, rev):
61 if rev not in self.basemap:
62 if rev <= self.repotiprev:
62 return revlog.revlog._chunk(self, rev)
63 return revlog.revlog._chunk(self, rev)
63 return self.revlog2._chunk(self.node(rev))
64 return self.revlog2._chunk(self.node(rev))
64
65
65 def revdiff(self, rev1, rev2):
66 def revdiff(self, rev1, rev2):
66 """return or calculate a delta between two revisions"""
67 """return or calculate a delta between two revisions"""
67 if rev1 in self.basemap and rev2 in self.basemap:
68 if rev1 > self.repotiprev and rev2 > self.repotiprev:
68 return self.revlog2.revdiff(
69 return self.revlog2.revdiff(
69 self.revlog2.rev(self.node(rev1)),
70 self.revlog2.rev(self.node(rev1)),
70 self.revlog2.rev(self.node(rev2)))
71 self.revlog2.rev(self.node(rev2)))
71 elif rev1 not in self.basemap and rev2 not in self.basemap:
72 elif rev1 <= self.repotiprev and rev2 <= self.repotiprev:
72 return revlog.revlog.revdiff(self, rev1, rev2)
73 return revlog.revlog.revdiff(self, rev1, rev2)
73
74
74 return mdiff.textdiff(self.revision(self.node(rev1)),
75 return mdiff.textdiff(self.revision(self.node(rev1)),
@@ -88,7 +89,7 b' class unionrevlog(revlog.revlog):'
88 if node == nullid:
89 if node == nullid:
89 return ""
90 return ""
90
91
91 if rev in self.basemap:
92 if rev > self.repotiprev:
92 text = self.revlog2.revision(node)
93 text = self.revlog2.revision(node)
93 self._cache = (node, rev, text)
94 self._cache = (node, rev, text)
94 else:
95 else:
@@ -144,7 +145,7 b' class unionrepository(localrepo.localrep'
144 util.expandpath(path2))
145 util.expandpath(path2))
145 self.repo2 = localrepo.localrepository(ui, path2)
146 self.repo2 = localrepo.localrepository(ui, path2)
146
147
147 @util.propertycache
148 @localrepo.unfilteredpropertycache
148 def changelog(self):
149 def changelog(self):
149 return unionchangelog(self.sopener, self.repo2.sopener)
150 return unionchangelog(self.sopener, self.repo2.sopener)
150
151
@@ -153,7 +154,7 b' class unionrepository(localrepo.localrep'
153 node = self.repo2.changelog.node(rev2)
154 node = self.repo2.changelog.node(rev2)
154 return self.changelog.rev(node)
155 return self.changelog.rev(node)
155
156
156 @util.propertycache
157 @localrepo.unfilteredpropertycache
157 def manifest(self):
158 def manifest(self):
158 return unionmanifest(self.sopener, self.repo2.sopener,
159 return unionmanifest(self.sopener, self.repo2.sopener,
159 self._clrev)
160 self._clrev)
@@ -174,8 +175,34 b' class unionrepository(localrepo.localrep'
174 def peer(self):
175 def peer(self):
175 return unionpeer(self)
176 return unionpeer(self)
176
177
178 def getcwd(self):
179 return os.getcwd() # always outside the repo
180
177 def instance(ui, path, create):
181 def instance(ui, path, create):
178 u = util.url(path)
182 if create:
179 assert u.scheme == 'union'
183 raise util.Abort(_('cannot create new union repository'))
180 repopath, repopath2 = u.path.split("+", 1)
184 parentpath = ui.config("bundle", "mainreporoot", "")
185 if not parentpath:
186 # try to find the correct path to the working directory repo
187 parentpath = cmdutil.findrepo(os.getcwd())
188 if parentpath is None:
189 parentpath = ''
190 if parentpath:
191 # Try to make the full path relative so we get a nice, short URL.
192 # In particular, we don't want temp dir names in test outputs.
193 cwd = os.getcwd()
194 if parentpath == cwd:
195 parentpath = ''
196 else:
197 cwd = os.path.join(cwd,'')
198 if parentpath.startswith(cwd):
199 parentpath = parentpath[len(cwd):]
200 if path.startswith('union:'):
201 s = path.split(":", 1)[1].split("+", 1)
202 if len(s) == 1:
203 repopath, repopath2 = parentpath, s[0]
204 else:
205 repopath, repopath2 = s
206 else:
207 repopath, repopath2 = parentpath, path
181 return unionrepository(ui, repopath, repopath2)
208 return unionrepository(ui, repopath, repopath2)
@@ -2,71 +2,71 b' import os'
2
2
3
3
4 class LockFile(object):
4 class LockFile(object):
5 """Provides methods to obtain, check for, and release a file based lock which
5 """Provides methods to obtain, check for, and release a file based lock which
6 should be used to handle concurrent access to the same file.
6 should be used to handle concurrent access to the same file.
7
7
8 As we are a utility class to be derived from, we only use protected methods.
8 As we are a utility class to be derived from, we only use protected methods.
9
9
10 Locks will automatically be released on destruction"""
10 Locks will automatically be released on destruction"""
11 __slots__ = ("_file_path", "_owns_lock")
11 __slots__ = ("_file_path", "_owns_lock")
12
12
13 def __init__(self, file_path):
13 def __init__(self, file_path):
14 self._file_path = file_path
14 self._file_path = file_path
15 self._owns_lock = False
15 self._owns_lock = False
16
16
17 def __del__(self):
17 def __del__(self):
18 self._release_lock()
18 self._release_lock()
19
19
20 def _lock_file_path(self):
20 def _lock_file_path(self):
21 """:return: Path to lockfile"""
21 """:return: Path to lockfile"""
22 return "%s.lock" % (self._file_path)
22 return "%s.lock" % (self._file_path)
23
23
24 def _has_lock(self):
24 def _has_lock(self):
25 """:return: True if we have a lock and if the lockfile still exists
25 """:return: True if we have a lock and if the lockfile still exists
26 :raise AssertionError: if our lock-file does not exist"""
26 :raise AssertionError: if our lock-file does not exist"""
27 if not self._owns_lock:
27 if not self._owns_lock:
28 return False
28 return False
29
29
30 return True
30 return True
31
31
32 def _obtain_lock_or_raise(self):
32 def _obtain_lock_or_raise(self):
33 """Create a lock file as flag for other instances, mark our instance as lock-holder
33 """Create a lock file as flag for other instances, mark our instance as lock-holder
34
34
35 :raise IOError: if a lock was already present or a lock file could not be written"""
35 :raise IOError: if a lock was already present or a lock file could not be written"""
36 if self._has_lock():
36 if self._has_lock():
37 return
37 return
38 lock_file = self._lock_file_path()
38 lock_file = self._lock_file_path()
39 if os.path.isfile(lock_file):
39 if os.path.isfile(lock_file):
40 raise IOError("Lock for file %r did already exist, delete %r in case the lock is illegal" % (self._file_path, lock_file))
40 raise IOError("Lock for file %r did already exist, delete %r in case the lock is illegal" % (self._file_path, lock_file))
41
41
42 try:
42 try:
43 fd = os.open(lock_file, os.O_WRONLY | os.O_CREAT | os.O_EXCL, 0)
43 fd = os.open(lock_file, os.O_WRONLY | os.O_CREAT | os.O_EXCL, 0)
44 os.close(fd)
44 os.close(fd)
45 except OSError,e:
45 except OSError,e:
46 raise IOError(str(e))
46 raise IOError(str(e))
47
47
48 self._owns_lock = True
48 self._owns_lock = True
49
49
50 def _obtain_lock(self):
50 def _obtain_lock(self):
51 """The default implementation will raise if a lock cannot be obtained.
51 """The default implementation will raise if a lock cannot be obtained.
52 Subclasses may override this method to provide a different implementation"""
52 Subclasses may override this method to provide a different implementation"""
53 return self._obtain_lock_or_raise()
53 return self._obtain_lock_or_raise()
54
54
55 def _release_lock(self):
55 def _release_lock(self):
56 """Release our lock if we have one"""
56 """Release our lock if we have one"""
57 if not self._has_lock():
57 if not self._has_lock():
58 return
58 return
59
59
60 # if someone removed our file beforhand, lets just flag this issue
60 # if someone removed our file beforhand, lets just flag this issue
61 # instead of failing, to make it more usable.
61 # instead of failing, to make it more usable.
62 lfp = self._lock_file_path()
62 lfp = self._lock_file_path()
63 try:
63 try:
64 # on bloody windows, the file needs write permissions to be removable.
64 # on bloody windows, the file needs write permissions to be removable.
65 # Why ...
65 # Why ...
66 if os.name == 'nt':
66 if os.name == 'nt':
67 os.chmod(lfp, 0777)
67 os.chmod(lfp, 0777)
68 # END handle win32
68 # END handle win32
69 os.remove(lfp)
69 os.remove(lfp)
70 except OSError:
70 except OSError:
71 pass
71 pass
72 self._owns_lock = False
72 self._owns_lock = False
@@ -35,6 +35,7 b' from rhodecode.model import BaseModel'
35 from rhodecode.model.db import ChangesetComment, User, Repository, \
35 from rhodecode.model.db import ChangesetComment, User, Repository, \
36 Notification, PullRequest
36 Notification, PullRequest
37 from rhodecode.model.notification import NotificationModel
37 from rhodecode.model.notification import NotificationModel
38 from rhodecode.model.meta import Session
38
39
39 log = logging.getLogger(__name__)
40 log = logging.getLogger(__name__)
40
41
@@ -57,8 +58,103 b' class ChangesetCommentsModel(BaseModel):'
57 user_objects.append(user_obj)
58 user_objects.append(user_obj)
58 return user_objects
59 return user_objects
59
60
61 def _get_notification_data(self, repo, comment, user, comment_text,
62 line_no=None, revision=None, pull_request=None,
63 status_change=None, closing_pr=False):
64 """
65 Get notification data
66
67 :param comment_text:
68 :param line:
69 :returns: tuple (subj,body,recipients,notification_type,email_kwargs)
70 """
71 # make notification
72 body = comment_text # text of the comment
73 line = ''
74 if line_no:
75 line = _('on line %s') % line_no
76
77 #changeset
78 if revision:
79 notification_type = Notification.TYPE_CHANGESET_COMMENT
80 cs = repo.scm_instance.get_changeset(revision)
81 desc = "%s" % (cs.short_id)
82
83 _url = h.url('changeset_home',
84 repo_name=repo.repo_name,
85 revision=revision,
86 anchor='comment-%s' % comment.comment_id,
87 qualified=True,
88 )
89 subj = safe_unicode(
90 h.link_to('Re changeset: %(desc)s %(line)s' % \
91 {'desc': desc, 'line': line},
92 _url)
93 )
94 email_subject = 'User %s commented on changeset %s' % \
95 (user.username, h.short_id(revision))
96 # get the current participants of this changeset
97 recipients = ChangesetComment.get_users(revision=revision)
98 # add changeset author if it's in rhodecode system
99 cs_author = User.get_from_cs_author(cs.author)
100 if not cs_author:
101 #use repo owner if we cannot extract the author correctly
102 cs_author = repo.user
103 recipients += [cs_author]
104 email_kwargs = {
105 'status_change': status_change,
106 'cs_comment_user': h.person(user.email),
107 'cs_target_repo': h.url('summary_home', repo_name=repo.repo_name,
108 qualified=True),
109 'cs_comment_url': _url,
110 'raw_id': revision,
111 'message': cs.message
112 }
113 #pull request
114 elif pull_request:
115 notification_type = Notification.TYPE_PULL_REQUEST_COMMENT
116 desc = comment.pull_request.title
117 _url = h.url('pullrequest_show',
118 repo_name=pull_request.other_repo.repo_name,
119 pull_request_id=pull_request.pull_request_id,
120 anchor='comment-%s' % comment.comment_id,
121 qualified=True,
122 )
123 subj = safe_unicode(
124 h.link_to('Re pull request #%(pr_id)s: %(desc)s %(line)s' % \
125 {'desc': desc,
126 'pr_id': comment.pull_request.pull_request_id,
127 'line': line},
128 _url)
129 )
130 email_subject = 'User %s commented on pull request #%s' % \
131 (user.username, comment.pull_request.pull_request_id)
132 # get the current participants of this pull request
133 recipients = ChangesetComment.get_users(pull_request_id=
134 pull_request.pull_request_id)
135 # add pull request author
136 recipients += [pull_request.author]
137
138 # add the reviewers to notification
139 recipients += [x.user for x in pull_request.reviewers]
140
141 #set some variables for email notification
142 email_kwargs = {
143 'pr_id': pull_request.pull_request_id,
144 'status_change': status_change,
145 'closing_pr': closing_pr,
146 'pr_comment_url': _url,
147 'pr_comment_user': h.person(user.email),
148 'pr_target_repo': h.url('summary_home',
149 repo_name=pull_request.other_repo.repo_name,
150 qualified=True)
151 }
152
153 return subj, body, recipients, notification_type, email_kwargs, email_subject
154
60 def create(self, text, repo, user, revision=None, pull_request=None,
155 def create(self, text, repo, user, revision=None, pull_request=None,
61 f_path=None, line_no=None, status_change=None, send_email=True):
156 f_path=None, line_no=None, status_change=None, closing_pr=False,
157 send_email=True):
62 """
158 """
63 Creates new comment for changeset or pull request.
159 Creates new comment for changeset or pull request.
64 IF status_change is not none this comment is associated with a
160 IF status_change is not none this comment is associated with a
@@ -72,9 +168,11 b' class ChangesetCommentsModel(BaseModel):'
72 :param f_path:
168 :param f_path:
73 :param line_no:
169 :param line_no:
74 :param status_change:
170 :param status_change:
171 :param closing_pr:
75 :param send_email:
172 :param send_email:
76 """
173 """
77 if not text:
174 if not text:
175 log.warning('Missing text for comment, skipping...')
78 return
176 return
79
177
80 repo = self._get_repo(repo)
178 repo = self._get_repo(repo)
@@ -87,8 +185,6 b' class ChangesetCommentsModel(BaseModel):'
87 comment.line_no = line_no
185 comment.line_no = line_no
88
186
89 if revision:
187 if revision:
90 cs = repo.scm_instance.get_changeset(revision)
91 desc = "%s - %s" % (cs.short_id, h.shorter(cs.message, 256))
92 comment.revision = revision
188 comment.revision = revision
93 elif pull_request:
189 elif pull_request:
94 pull_request = self.__get_pull_request(pull_request)
190 pull_request = self.__get_pull_request(pull_request)
@@ -96,82 +192,24 b' class ChangesetCommentsModel(BaseModel):'
96 else:
192 else:
97 raise Exception('Please specify revision or pull_request_id')
193 raise Exception('Please specify revision or pull_request_id')
98
194
99 self.sa.add(comment)
195 Session().add(comment)
100 self.sa.flush()
196 Session().flush()
101
102 # make notification
103 line = ''
104 body = text
105
106 #changeset
107 if revision:
108 if line_no:
109 line = _('on line %s') % line_no
110 subj = safe_unicode(
111 h.link_to('Re commit: %(desc)s %(line)s' % \
112 {'desc': desc, 'line': line},
113 h.url('changeset_home', repo_name=repo.repo_name,
114 revision=revision,
115 anchor='comment-%s' % comment.comment_id,
116 qualified=True,
117 )
118 )
119 )
120 notification_type = Notification.TYPE_CHANGESET_COMMENT
121 # get the current participants of this changeset
122 recipients = ChangesetComment.get_users(revision=revision)
123 # add changeset author if it's in rhodecode system
124 cs_author = User.get_from_cs_author(cs.author)
125 if not cs_author:
126 #use repo owner if we cannot extract the author correctly
127 cs_author = repo.user
128 recipients += [cs_author]
129 email_kwargs = {
130 'status_change': status_change,
131 }
132 #pull request
133 elif pull_request:
134 _url = h.url('pullrequest_show',
135 repo_name=pull_request.other_repo.repo_name,
136 pull_request_id=pull_request.pull_request_id,
137 anchor='comment-%s' % comment.comment_id,
138 qualified=True,
139 )
140 subj = safe_unicode(
141 h.link_to('Re pull request #%(pr_id)s: %(desc)s %(line)s' % \
142 {'desc': comment.pull_request.title,
143 'pr_id': comment.pull_request.pull_request_id,
144 'line': line},
145 _url)
146 )
147
148 notification_type = Notification.TYPE_PULL_REQUEST_COMMENT
149 # get the current participants of this pull request
150 recipients = ChangesetComment.get_users(pull_request_id=
151 pull_request.pull_request_id)
152 # add pull request author
153 recipients += [pull_request.author]
154
155 # add the reviewers to notification
156 recipients += [x.user for x in pull_request.reviewers]
157
158 #set some variables for email notification
159 email_kwargs = {
160 'pr_id': pull_request.pull_request_id,
161 'status_change': status_change,
162 'pr_comment_url': _url,
163 'pr_comment_user': h.person(user.email),
164 'pr_target_repo': h.url('summary_home',
165 repo_name=pull_request.other_repo.repo_name,
166 qualified=True)
167 }
168
197
169 if send_email:
198 if send_email:
199 (subj, body, recipients, notification_type,
200 email_kwargs, email_subject) = self._get_notification_data(
201 repo, comment, user,
202 comment_text=text,
203 line_no=line_no,
204 revision=revision,
205 pull_request=pull_request,
206 status_change=status_change,
207 closing_pr=closing_pr)
170 # create notification objects, and emails
208 # create notification objects, and emails
171 NotificationModel().create(
209 NotificationModel().create(
172 created_by=user, subject=subj, body=body,
210 created_by=user, subject=subj, body=body,
173 recipients=recipients, type_=notification_type,
211 recipients=recipients, type_=notification_type,
174 email_kwargs=email_kwargs
212 email_kwargs=email_kwargs, email_subject=email_subject
175 )
213 )
176
214
177 mention_recipients = set(self._extract_mentions(body))\
215 mention_recipients = set(self._extract_mentions(body))\
@@ -195,7 +233,7 b' class ChangesetCommentsModel(BaseModel):'
195 :param comment_id:
233 :param comment_id:
196 """
234 """
197 comment = self.__get_changeset_comment(comment)
235 comment = self.__get_changeset_comment(comment)
198 self.sa.delete(comment)
236 Session().delete(comment)
199
237
200 return comment
238 return comment
201
239
@@ -204,11 +242,8 b' class ChangesetCommentsModel(BaseModel):'
204 Get's main comments based on revision or pull_request_id
242 Get's main comments based on revision or pull_request_id
205
243
206 :param repo_id:
244 :param repo_id:
207 :type repo_id:
208 :param revision:
245 :param revision:
209 :type revision:
210 :param pull_request:
246 :param pull_request:
211 :type pull_request:
212 """
247 """
213
248
214 q = ChangesetComment.query()\
249 q = ChangesetComment.query()\
@@ -226,7 +261,7 b' class ChangesetCommentsModel(BaseModel):'
226 return q.all()
261 return q.all()
227
262
228 def get_inline_comments(self, repo_id, revision=None, pull_request=None):
263 def get_inline_comments(self, repo_id, revision=None, pull_request=None):
229 q = self.sa.query(ChangesetComment)\
264 q = Session().query(ChangesetComment)\
230 .filter(ChangesetComment.repo_id == repo_id)\
265 .filter(ChangesetComment.repo_id == repo_id)\
231 .filter(ChangesetComment.line_no != None)\
266 .filter(ChangesetComment.line_no != None)\
232 .filter(ChangesetComment.f_path != None)\
267 .filter(ChangesetComment.f_path != None)\
@@ -44,6 +44,7 b' from rhodecode.lib.vcs import get_backen'
44 from rhodecode.lib.vcs.utils.helpers import get_scm
44 from rhodecode.lib.vcs.utils.helpers import get_scm
45 from rhodecode.lib.vcs.exceptions import VCSError
45 from rhodecode.lib.vcs.exceptions import VCSError
46 from rhodecode.lib.vcs.utils.lazy import LazyProperty
46 from rhodecode.lib.vcs.utils.lazy import LazyProperty
47 from rhodecode.lib.vcs.backends.base import EmptyChangeset
47
48
48 from rhodecode.lib.utils2 import str2bool, safe_str, get_changeset_safe, \
49 from rhodecode.lib.utils2 import str2bool, safe_str, get_changeset_safe, \
49 safe_unicode, remove_suffix, remove_prefix
50 safe_unicode, remove_suffix, remove_prefix
@@ -341,7 +342,7 b' class User(Base, BaseModel):'
341 repo_to_perm = relationship('UserRepoToPerm', primaryjoin='UserRepoToPerm.user_id==User.user_id', cascade='all')
342 repo_to_perm = relationship('UserRepoToPerm', primaryjoin='UserRepoToPerm.user_id==User.user_id', cascade='all')
342 repo_group_to_perm = relationship('UserRepoGroupToPerm', primaryjoin='UserRepoGroupToPerm.user_id==User.user_id', cascade='all')
343 repo_group_to_perm = relationship('UserRepoGroupToPerm', primaryjoin='UserRepoGroupToPerm.user_id==User.user_id', cascade='all')
343
344
344 group_member = relationship('UsersGroupMember', cascade='all')
345 group_member = relationship('UserGroupMember', cascade='all')
345
346
346 notifications = relationship('UserNotification', cascade='all')
347 notifications = relationship('UserNotification', cascade='all')
347 # notifications assigned to this user
348 # notifications assigned to this user
@@ -604,7 +605,7 b' class UserLog(Base, BaseModel):'
604 repository = relationship('Repository', cascade='')
605 repository = relationship('Repository', cascade='')
605
606
606
607
607 class UsersGroup(Base, BaseModel):
608 class UserGroup(Base, BaseModel):
608 __tablename__ = 'users_groups'
609 __tablename__ = 'users_groups'
609 __table_args__ = (
610 __table_args__ = (
610 {'extend_existing': True, 'mysql_engine': 'InnoDB',
611 {'extend_existing': True, 'mysql_engine': 'InnoDB',
@@ -616,9 +617,9 b' class UsersGroup(Base, BaseModel):'
616 users_group_active = Column("users_group_active", Boolean(), nullable=True, unique=None, default=None)
617 users_group_active = Column("users_group_active", Boolean(), nullable=True, unique=None, default=None)
617 inherit_default_permissions = Column("users_group_inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
618 inherit_default_permissions = Column("users_group_inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
618
619
619 members = relationship('UsersGroupMember', cascade="all, delete, delete-orphan", lazy="joined")
620 members = relationship('UserGroupMember', cascade="all, delete, delete-orphan", lazy="joined")
620 users_group_to_perm = relationship('UsersGroupToPerm', cascade='all')
621 users_group_to_perm = relationship('UserGroupToPerm', cascade='all')
621 users_group_repo_to_perm = relationship('UsersGroupRepoToPerm', cascade='all')
622 users_group_repo_to_perm = relationship('UserGroupRepoToPerm', cascade='all')
622
623
623 def __unicode__(self):
624 def __unicode__(self):
624 return u'<userGroup(%s)>' % (self.users_group_name)
625 return u'<userGroup(%s)>' % (self.users_group_name)
@@ -658,7 +659,7 b' class UsersGroup(Base, BaseModel):'
658 return data
659 return data
659
660
660
661
661 class UsersGroupMember(Base, BaseModel):
662 class UserGroupMember(Base, BaseModel):
662 __tablename__ = 'users_groups_members'
663 __tablename__ = 'users_groups_members'
663 __table_args__ = (
664 __table_args__ = (
664 {'extend_existing': True, 'mysql_engine': 'InnoDB',
665 {'extend_existing': True, 'mysql_engine': 'InnoDB',
@@ -670,7 +671,7 b' class UsersGroupMember(Base, BaseModel):'
670 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
671 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
671
672
672 user = relationship('User', lazy='joined')
673 user = relationship('User', lazy='joined')
673 users_group = relationship('UsersGroup')
674 users_group = relationship('UserGroup')
674
675
675 def __init__(self, gr_id='', u_id=''):
676 def __init__(self, gr_id='', u_id=''):
676 self.users_group_id = gr_id
677 self.users_group_id = gr_id
@@ -747,7 +748,7 b' class Repository(Base, BaseModel):'
747 fork = relationship('Repository', remote_side=repo_id)
748 fork = relationship('Repository', remote_side=repo_id)
748 group = relationship('RepoGroup')
749 group = relationship('RepoGroup')
749 repo_to_perm = relationship('UserRepoToPerm', cascade='all', order_by='UserRepoToPerm.repo_to_perm_id')
750 repo_to_perm = relationship('UserRepoToPerm', cascade='all', order_by='UserRepoToPerm.repo_to_perm_id')
750 users_group_to_perm = relationship('UsersGroupRepoToPerm', cascade='all')
751 users_group_to_perm = relationship('UserGroupRepoToPerm', cascade='all')
751 stats = relationship('Statistics', cascade='all', uselist=False)
752 stats = relationship('Statistics', cascade='all', uselist=False)
752
753
753 followers = relationship('UserFollowing',
754 followers = relationship('UserFollowing',
@@ -1053,15 +1054,18 b' class Repository(Base, BaseModel):'
1053 """
1054 """
1054 from rhodecode.lib.vcs.backends.base import BaseChangeset
1055 from rhodecode.lib.vcs.backends.base import BaseChangeset
1055 if cs_cache is None:
1056 if cs_cache is None:
1056 cs_cache = self.get_changeset()
1057 cs_cache = EmptyChangeset()
1058 # use no-cache version here
1059 scm_repo = self.scm_instance_no_cache
1060 if scm_repo:
1061 cs_cache = scm_repo.get_changeset()
1062
1057 if isinstance(cs_cache, BaseChangeset):
1063 if isinstance(cs_cache, BaseChangeset):
1058 cs_cache = cs_cache.__json__()
1064 cs_cache = cs_cache.__json__()
1059
1065
1060 if (cs_cache != self.changeset_cache
1066 if (cs_cache != self.changeset_cache or not self.changeset_cache):
1061 or not self.last_change
1062 or not self.changeset_cache):
1063 _default = datetime.datetime.fromtimestamp(0)
1067 _default = datetime.datetime.fromtimestamp(0)
1064 last_change = cs_cache.get('date') or self.last_change or _default
1068 last_change = cs_cache.get('date') or _default
1065 log.debug('updated repo %s with new cs cache %s' % (self, cs_cache))
1069 log.debug('updated repo %s with new cs cache %s' % (self, cs_cache))
1066 self.updated_on = last_change
1070 self.updated_on = last_change
1067 self.changeset_cache = cs_cache
1071 self.changeset_cache = cs_cache
@@ -1188,7 +1192,8 b' class Repository(Base, BaseModel):'
1188 repo_full_path = self.repo_full_path
1192 repo_full_path = self.repo_full_path
1189 try:
1193 try:
1190 alias = get_scm(repo_full_path)[0]
1194 alias = get_scm(repo_full_path)[0]
1191 log.debug('Creating instance of %s repository' % alias)
1195 log.debug('Creating instance of %s repository from %s'
1196 % (alias, repo_full_path))
1192 backend = get_backend(alias)
1197 backend = get_backend(alias)
1193 except VCSError:
1198 except VCSError:
1194 log.error(traceback.format_exc())
1199 log.error(traceback.format_exc())
@@ -1227,7 +1232,7 b' class RepoGroup(Base, BaseModel):'
1227 enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
1232 enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
1228
1233
1229 repo_group_to_perm = relationship('UserRepoGroupToPerm', cascade='all', order_by='UserRepoGroupToPerm.group_to_perm_id')
1234 repo_group_to_perm = relationship('UserRepoGroupToPerm', cascade='all', order_by='UserRepoGroupToPerm.group_to_perm_id')
1230 users_group_to_perm = relationship('UsersGroupRepoGroupToPerm', cascade='all')
1235 users_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all')
1231
1236
1232 parent_group = relationship('RepoGroup', remote_side=group_id)
1237 parent_group = relationship('RepoGroup', remote_side=group_id)
1233
1238
@@ -1378,10 +1383,10 b' class Permission(Base, BaseModel):'
1378 ('repository.write', _('Repository write access')),
1383 ('repository.write', _('Repository write access')),
1379 ('repository.admin', _('Repository admin access')),
1384 ('repository.admin', _('Repository admin access')),
1380
1385
1381 ('group.none', _('Repositories Group no access')),
1386 ('group.none', _('Repository group no access')),
1382 ('group.read', _('Repositories Group read access')),
1387 ('group.read', _('Repository group read access')),
1383 ('group.write', _('Repositories Group write access')),
1388 ('group.write', _('Repository group write access')),
1384 ('group.admin', _('Repositories Group admin access')),
1389 ('group.admin', _('Repository group admin access')),
1385
1390
1386 ('hg.admin', _('RhodeCode Administrator')),
1391 ('hg.admin', _('RhodeCode Administrator')),
1387 ('hg.create.none', _('Repository creation disabled')),
1392 ('hg.create.none', _('Repository creation disabled')),
@@ -1490,7 +1495,7 b' class UserToPerm(Base, BaseModel):'
1490 permission = relationship('Permission', lazy='joined')
1495 permission = relationship('Permission', lazy='joined')
1491
1496
1492
1497
1493 class UsersGroupRepoToPerm(Base, BaseModel):
1498 class UserGroupRepoToPerm(Base, BaseModel):
1494 __tablename__ = 'users_group_repo_to_perm'
1499 __tablename__ = 'users_group_repo_to_perm'
1495 __table_args__ = (
1500 __table_args__ = (
1496 UniqueConstraint('repository_id', 'users_group_id', 'permission_id'),
1501 UniqueConstraint('repository_id', 'users_group_id', 'permission_id'),
@@ -1502,7 +1507,7 b' class UsersGroupRepoToPerm(Base, BaseMod'
1502 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
1507 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
1503 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
1508 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
1504
1509
1505 users_group = relationship('UsersGroup')
1510 users_group = relationship('UserGroup')
1506 permission = relationship('Permission')
1511 permission = relationship('Permission')
1507 repository = relationship('Repository')
1512 repository = relationship('Repository')
1508
1513
@@ -1519,7 +1524,7 b' class UsersGroupRepoToPerm(Base, BaseMod'
1519 return u'<userGroup:%s => %s >' % (self.users_group, self.repository)
1524 return u'<userGroup:%s => %s >' % (self.users_group, self.repository)
1520
1525
1521
1526
1522 class UsersGroupToPerm(Base, BaseModel):
1527 class UserGroupToPerm(Base, BaseModel):
1523 __tablename__ = 'users_group_to_perm'
1528 __tablename__ = 'users_group_to_perm'
1524 __table_args__ = (
1529 __table_args__ = (
1525 UniqueConstraint('users_group_id', 'permission_id',),
1530 UniqueConstraint('users_group_id', 'permission_id',),
@@ -1530,7 +1535,7 b' class UsersGroupToPerm(Base, BaseModel):'
1530 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
1535 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
1531 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
1536 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
1532
1537
1533 users_group = relationship('UsersGroup')
1538 users_group = relationship('UserGroup')
1534 permission = relationship('Permission')
1539 permission = relationship('Permission')
1535
1540
1536
1541
@@ -1552,7 +1557,7 b' class UserRepoGroupToPerm(Base, BaseMode'
1552 permission = relationship('Permission')
1557 permission = relationship('Permission')
1553
1558
1554
1559
1555 class UsersGroupRepoGroupToPerm(Base, BaseModel):
1560 class UserGroupRepoGroupToPerm(Base, BaseModel):
1556 __tablename__ = 'users_group_repo_group_to_perm'
1561 __tablename__ = 'users_group_repo_group_to_perm'
1557 __table_args__ = (
1562 __table_args__ = (
1558 UniqueConstraint('users_group_id', 'group_id'),
1563 UniqueConstraint('users_group_id', 'group_id'),
@@ -1565,7 +1570,7 b' class UsersGroupRepoGroupToPerm(Base, Ba'
1565 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
1570 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
1566 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
1571 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
1567
1572
1568 users_group = relationship('UsersGroup')
1573 users_group = relationship('UserGroup')
1569 permission = relationship('Permission')
1574 permission = relationship('Permission')
1570 group = relationship('RepoGroup')
1575 group = relationship('RepoGroup')
1571
1576
@@ -94,14 +94,14 b' def UserForm(edit=False, old_data={}):'
94 return _UserForm
94 return _UserForm
95
95
96
96
97 def UsersGroupForm(edit=False, old_data={}, available_members=[]):
97 def UserGroupForm(edit=False, old_data={}, available_members=[]):
98 class _UsersGroupForm(formencode.Schema):
98 class _UserGroupForm(formencode.Schema):
99 allow_extra_fields = True
99 allow_extra_fields = True
100 filter_extra_fields = True
100 filter_extra_fields = True
101
101
102 users_group_name = All(
102 users_group_name = All(
103 v.UnicodeString(strip=True, min=1, not_empty=True),
103 v.UnicodeString(strip=True, min=1, not_empty=True),
104 v.ValidUsersGroup(edit, old_data)
104 v.ValidUserGroup(edit, old_data)
105 )
105 )
106
106
107 users_group_active = v.StringBoolean(if_missing=False)
107 users_group_active = v.StringBoolean(if_missing=False)
@@ -112,7 +112,7 b' def UsersGroupForm(edit=False, old_data='
112 if_missing=None, not_empty=False
112 if_missing=None, not_empty=False
113 )
113 )
114
114
115 return _UsersGroupForm
115 return _UserGroupForm
116
116
117
117
118 def ReposGroupForm(edit=False, old_data={}, available_groups=[],
118 def ReposGroupForm(edit=False, old_data={}, available_groups=[],
@@ -28,12 +28,14 b' import os'
28 import logging
28 import logging
29 import traceback
29 import traceback
30
30
31 from pylons import tmpl_context as c
31 from pylons.i18n.translation import _
32 from pylons.i18n.translation import _
32
33
33 import rhodecode
34 import rhodecode
34 from rhodecode.lib import helpers as h
35 from rhodecode.lib import helpers as h
35 from rhodecode.model import BaseModel
36 from rhodecode.model import BaseModel
36 from rhodecode.model.db import Notification, User, UserNotification
37 from rhodecode.model.db import Notification, User, UserNotification
38 from rhodecode.model.meta import Session
37
39
38 log = logging.getLogger(__name__)
40 log = logging.getLogger(__name__)
39
41
@@ -54,7 +56,7 b' class NotificationModel(BaseModel):'
54
56
55 def create(self, created_by, subject, body, recipients=None,
57 def create(self, created_by, subject, body, recipients=None,
56 type_=Notification.TYPE_MESSAGE, with_email=True,
58 type_=Notification.TYPE_MESSAGE, with_email=True,
57 email_kwargs={}):
59 email_kwargs={}, email_subject=None):
58 """
60 """
59
61
60 Creates notification of given type
62 Creates notification of given type
@@ -68,6 +70,7 b' class NotificationModel(BaseModel):'
68 :param type_: type of notification
70 :param type_: type of notification
69 :param with_email: send email with this notification
71 :param with_email: send email with this notification
70 :param email_kwargs: additional dict to pass as args to email template
72 :param email_kwargs: additional dict to pass as args to email template
73 :param email_subject: use given subject as email subject
71 """
74 """
72 from rhodecode.lib.celerylib import tasks, run_task
75 from rhodecode.lib.celerylib import tasks, run_task
73
76
@@ -105,9 +108,11 b' class NotificationModel(BaseModel):'
105
108
106 # send email with notification to all other participants
109 # send email with notification to all other participants
107 for rec in rec_objs:
110 for rec in rec_objs:
108 email_subject = NotificationModel().make_description(notif, False)
111 if not email_subject:
112 email_subject = NotificationModel()\
113 .make_description(notif, show_age=False)
109 type_ = type_
114 type_ = type_
110 email_body = body
115 email_body = None # we set body to none, we just send HTML emails
111 ## this is passed into template
116 ## this is passed into template
112 kwargs = {'subject': subject, 'body': h.rst_w_mentions(body)}
117 kwargs = {'subject': subject, 'body': h.rst_w_mentions(body)}
113 kwargs.update(email_kwargs)
118 kwargs.update(email_kwargs)
@@ -130,7 +135,7 b' class NotificationModel(BaseModel):'
130 .filter(UserNotification.notification
135 .filter(UserNotification.notification
131 == notification)\
136 == notification)\
132 .one()
137 .one()
133 self.sa.delete(obj)
138 Session().delete(obj)
134 return True
139 return True
135 except Exception:
140 except Exception:
136 log.error(traceback.format_exc())
141 log.error(traceback.format_exc())
@@ -141,7 +146,6 b' class NotificationModel(BaseModel):'
141 Get mentions for given user, filter them if filter dict is given
146 Get mentions for given user, filter them if filter dict is given
142
147
143 :param user:
148 :param user:
144 :type user:
145 :param filter:
149 :param filter:
146 """
150 """
147 user = self._get_user(user)
151 user = self._get_user(user)
@@ -167,7 +171,7 b' class NotificationModel(BaseModel):'
167 == notification)\
171 == notification)\
168 .one()
172 .one()
169 obj.read = True
173 obj.read = True
170 self.sa.add(obj)
174 Session().add(obj)
171 return True
175 return True
172 except Exception:
176 except Exception:
173 log.error(traceback.format_exc())
177 log.error(traceback.format_exc())
@@ -187,7 +191,7 b' class NotificationModel(BaseModel):'
187 # update on joined tables :(
191 # update on joined tables :(
188 for obj in q.all():
192 for obj in q.all():
189 obj.read = True
193 obj.read = True
190 self.sa.add(obj)
194 Session().add(obj)
191
195
192 def get_unread_cnt_for_user(self, user):
196 def get_unread_cnt_for_user(self, user):
193 user = self._get_user(user)
197 user = self._get_user(user)
@@ -217,7 +221,7 b' class NotificationModel(BaseModel):'
217 #alias
221 #alias
218 _n = notification
222 _n = notification
219 _map = {
223 _map = {
220 _n.TYPE_CHANGESET_COMMENT: _('commented on commit at %(when)s'),
224 _n.TYPE_CHANGESET_COMMENT: _('commented on changeset at %(when)s'),
221 _n.TYPE_MESSAGE: _('sent message at %(when)s'),
225 _n.TYPE_MESSAGE: _('sent message at %(when)s'),
222 _n.TYPE_MENTION: _('mentioned you at %(when)s'),
226 _n.TYPE_MENTION: _('mentioned you at %(when)s'),
223 _n.TYPE_REGISTRATION: _('registered in RhodeCode at %(when)s'),
227 _n.TYPE_REGISTRATION: _('registered in RhodeCode at %(when)s'),
@@ -272,7 +276,8 b' class EmailNotificationModel(BaseModel):'
272 email_template = self._tmpl_lookup.get_template(base)
276 email_template = self._tmpl_lookup.get_template(base)
273 # translator and helpers inject
277 # translator and helpers inject
274 _kwargs = {'_': _,
278 _kwargs = {'_': _,
275 'h': h}
279 'h': h,
280 'c': c}
276 _kwargs.update(kwargs)
281 _kwargs.update(kwargs)
277 log.debug('rendering tmpl %s with kwargs %s' % (base, _kwargs))
282 log.debug('rendering tmpl %s with kwargs %s' % (base, _kwargs))
278 return email_template.render(**_kwargs)
283 return email_template.render(**_kwargs)
@@ -75,13 +75,13 b' class PullRequestModel(BaseModel):'
75 new.title = title
75 new.title = title
76 new.description = description
76 new.description = description
77 new.author = created_by_user
77 new.author = created_by_user
78 self.sa.add(new)
78 Session().add(new)
79 Session().flush()
79 Session().flush()
80 #members
80 #members
81 for member in set(reviewers):
81 for member in set(reviewers):
82 _usr = self._get_user(member)
82 _usr = self._get_user(member)
83 reviewer = PullRequestReviewers(_usr, new)
83 reviewer = PullRequestReviewers(_usr, new)
84 self.sa.add(reviewer)
84 Session().add(reviewer)
85
85
86 #reset state to under-review
86 #reset state to under-review
87 ChangesetStatusModel().set_status(
87 ChangesetStatusModel().set_status(
@@ -90,7 +90,8 b' class PullRequestModel(BaseModel):'
90 user=created_by_user,
90 user=created_by_user,
91 pull_request=new
91 pull_request=new
92 )
92 )
93
93 revision_data = [(x.raw_id, x.message)
94 for x in map(org_repo.get_changeset, revisions)]
94 #notification to reviewers
95 #notification to reviewers
95 notif = NotificationModel()
96 notif = NotificationModel()
96
97
@@ -114,7 +115,7 b' class PullRequestModel(BaseModel):'
114 'pr_repo_url': h.url('summary_home', repo_name=other_repo.repo_name,
115 'pr_repo_url': h.url('summary_home', repo_name=other_repo.repo_name,
115 qualified=True,),
116 qualified=True,),
116 'pr_url': pr_url,
117 'pr_url': pr_url,
117 'pr_revisions': revisions
118 'pr_revisions': revision_data
118 }
119 }
119
120
120 notif.create(created_by=created_by_user, subject=subject, body=body,
121 notif.create(created_by=created_by_user, subject=subject, body=body,
@@ -140,7 +141,7 b' class PullRequestModel(BaseModel):'
140 for uid in to_add:
141 for uid in to_add:
141 _usr = self._get_user(uid)
142 _usr = self._get_user(uid)
142 reviewer = PullRequestReviewers(_usr, pull_request)
143 reviewer = PullRequestReviewers(_usr, pull_request)
143 self.sa.add(reviewer)
144 Session().add(reviewer)
144
145
145 for uid in to_remove:
146 for uid in to_remove:
146 reviewer = PullRequestReviewers.query()\
147 reviewer = PullRequestReviewers.query()\
@@ -148,7 +149,7 b' class PullRequestModel(BaseModel):'
148 PullRequestReviewers.pull_request==pull_request)\
149 PullRequestReviewers.pull_request==pull_request)\
149 .scalar()
150 .scalar()
150 if reviewer:
151 if reviewer:
151 self.sa.delete(reviewer)
152 Session().delete(reviewer)
152
153
153 def delete(self, pull_request):
154 def delete(self, pull_request):
154 pull_request = self.__get_pull_request(pull_request)
155 pull_request = self.__get_pull_request(pull_request)
@@ -158,7 +159,7 b' class PullRequestModel(BaseModel):'
158 pull_request = self.__get_pull_request(pull_request)
159 pull_request = self.__get_pull_request(pull_request)
159 pull_request.status = PullRequest.STATUS_CLOSED
160 pull_request.status = PullRequest.STATUS_CLOSED
160 pull_request.updated_on = datetime.datetime.now()
161 pull_request.updated_on = datetime.datetime.now()
161 self.sa.add(pull_request)
162 Session().add(pull_request)
162
163
163 def _get_changesets(self, alias, org_repo, org_ref, other_repo, other_ref):
164 def _get_changesets(self, alias, org_repo, org_ref, other_repo, other_ref):
164 """
165 """
@@ -248,11 +249,7 b' class PullRequestModel(BaseModel):'
248 if len(other_ref) != 2 or not isinstance(org_ref, (list, tuple)):
249 if len(other_ref) != 2 or not isinstance(org_ref, (list, tuple)):
249 raise Exception('other_ref must be a two element list/tuple')
250 raise Exception('other_ref must be a two element list/tuple')
250
251
251 org_repo_scm = org_repo.scm_instance
252 cs_ranges, ancestor = self._get_changesets(org_repo.scm_instance.alias,
252 other_repo_scm = other_repo.scm_instance
253 org_repo.scm_instance, org_ref,
253
254 other_repo.scm_instance, other_ref)
254 alias = org_repo.scm_instance.alias
255 cs_ranges, ancestor = self._get_changesets(alias,
256 org_repo_scm, org_ref,
257 other_repo_scm, other_ref)
258 return cs_ranges, ancestor
255 return cs_ranges, ancestor
@@ -38,7 +38,7 b' from rhodecode.lib.hooks import log_crea'
38
38
39 from rhodecode.model import BaseModel
39 from rhodecode.model import BaseModel
40 from rhodecode.model.db import Repository, UserRepoToPerm, User, Permission, \
40 from rhodecode.model.db import Repository, UserRepoToPerm, User, Permission, \
41 Statistics, UsersGroup, UsersGroupRepoToPerm, RhodeCodeUi, RepoGroup,\
41 Statistics, UserGroup, UserGroupRepoToPerm, RhodeCodeUi, RepoGroup,\
42 RhodeCodeSetting, RepositoryField
42 RhodeCodeSetting, RepositoryField
43 from rhodecode.lib import helpers as h
43 from rhodecode.lib import helpers as h
44 from rhodecode.lib.auth import HasRepoPermissionAny
44 from rhodecode.lib.auth import HasRepoPermissionAny
@@ -54,8 +54,8 b' class RepoModel(BaseModel):'
54 URL_SEPARATOR = Repository.url_sep()
54 URL_SEPARATOR = Repository.url_sep()
55
55
56 def __get_users_group(self, users_group):
56 def __get_users_group(self, users_group):
57 return self._get_instance(UsersGroup, users_group,
57 return self._get_instance(UserGroup, users_group,
58 callback=UsersGroup.get_by_group_name)
58 callback=UserGroup.get_by_group_name)
59
59
60 def _get_repos_group(self, repos_group):
60 def _get_repos_group(self, repos_group):
61 return self._get_instance(RepoGroup, repos_group,
61 return self._get_instance(RepoGroup, repos_group,
@@ -120,8 +120,8 b' class RepoModel(BaseModel):'
120 )
120 )
121
121
122 def get_users_groups_js(self):
122 def get_users_groups_js(self):
123 users_groups = self.sa.query(UsersGroup)\
123 users_groups = self.sa.query(UserGroup)\
124 .filter(UsersGroup.users_group_active == True).all()
124 .filter(UserGroup.users_group_active == True).all()
125
125
126 return json.dumps([
126 return json.dumps([
127 {
127 {
@@ -149,11 +149,7 b' class RepoModel(BaseModel):'
149 if not repositories:
149 if not repositories:
150 repositories = Repository.getAll()
150 repositories = Repository.getAll()
151 for repo in repositories:
151 for repo in repositories:
152 scm_repo = repo.scm_instance_no_cache
152 repo.update_changeset_cache()
153 last_cs = EmptyChangeset()
154 if scm_repo:
155 last_cs = scm_repo.get_changeset()
156 repo.update_changeset_cache(last_cs)
157
153
158 def get_repos_as_dict(self, repos_list=None, admin=False, perm_check=True,
154 def get_repos_as_dict(self, repos_list=None, admin=False, perm_check=True,
159 super_user_actions=False):
155 super_user_actions=False):
@@ -415,15 +411,15 b' class RepoModel(BaseModel):'
415 repo = fork_of
411 repo = fork_of
416 user_perms = UserRepoToPerm.query()\
412 user_perms = UserRepoToPerm.query()\
417 .filter(UserRepoToPerm.repository == repo).all()
413 .filter(UserRepoToPerm.repository == repo).all()
418 group_perms = UsersGroupRepoToPerm.query()\
414 group_perms = UserGroupRepoToPerm.query()\
419 .filter(UsersGroupRepoToPerm.repository == repo).all()
415 .filter(UserGroupRepoToPerm.repository == repo).all()
420
416
421 for perm in user_perms:
417 for perm in user_perms:
422 UserRepoToPerm.create(perm.user, new_repo,
418 UserRepoToPerm.create(perm.user, new_repo,
423 perm.permission)
419 perm.permission)
424
420
425 for perm in group_perms:
421 for perm in group_perms:
426 UsersGroupRepoToPerm.create(perm.users_group, new_repo,
422 UserGroupRepoToPerm.create(perm.users_group, new_repo,
427 perm.permission)
423 perm.permission)
428 else:
424 else:
429 _create_default_perms()
425 _create_default_perms()
@@ -549,12 +545,12 b' class RepoModel(BaseModel):'
549
545
550 def grant_users_group_permission(self, repo, group_name, perm):
546 def grant_users_group_permission(self, repo, group_name, perm):
551 """
547 """
552 Grant permission for users group on given repository, or update
548 Grant permission for user group on given repository, or update
553 existing one if found
549 existing one if found
554
550
555 :param repo: Instance of Repository, repository_id, or repository name
551 :param repo: Instance of Repository, repository_id, or repository name
556 :param group_name: Instance of UserGroup, users_group_id,
552 :param group_name: Instance of UserGroup, users_group_id,
557 or users group name
553 or user group name
558 :param perm: Instance of Permission, or permission_name
554 :param perm: Instance of Permission, or permission_name
559 """
555 """
560 repo = self._get_repo(repo)
556 repo = self._get_repo(repo)
@@ -562,14 +558,14 b' class RepoModel(BaseModel):'
562 permission = self._get_perm(perm)
558 permission = self._get_perm(perm)
563
559
564 # check if we have that permission already
560 # check if we have that permission already
565 obj = self.sa.query(UsersGroupRepoToPerm)\
561 obj = self.sa.query(UserGroupRepoToPerm)\
566 .filter(UsersGroupRepoToPerm.users_group == group_name)\
562 .filter(UserGroupRepoToPerm.users_group == group_name)\
567 .filter(UsersGroupRepoToPerm.repository == repo)\
563 .filter(UserGroupRepoToPerm.repository == repo)\
568 .scalar()
564 .scalar()
569
565
570 if obj is None:
566 if obj is None:
571 # create new
567 # create new
572 obj = UsersGroupRepoToPerm()
568 obj = UserGroupRepoToPerm()
573
569
574 obj.repository = repo
570 obj.repository = repo
575 obj.users_group = group_name
571 obj.users_group = group_name
@@ -579,18 +575,18 b' class RepoModel(BaseModel):'
579
575
580 def revoke_users_group_permission(self, repo, group_name):
576 def revoke_users_group_permission(self, repo, group_name):
581 """
577 """
582 Revoke permission for users group on given repository
578 Revoke permission for user group on given repository
583
579
584 :param repo: Instance of Repository, repository_id, or repository name
580 :param repo: Instance of Repository, repository_id, or repository name
585 :param group_name: Instance of UserGroup, users_group_id,
581 :param group_name: Instance of UserGroup, users_group_id,
586 or users group name
582 or user group name
587 """
583 """
588 repo = self._get_repo(repo)
584 repo = self._get_repo(repo)
589 group_name = self.__get_users_group(group_name)
585 group_name = self.__get_users_group(group_name)
590
586
591 obj = self.sa.query(UsersGroupRepoToPerm)\
587 obj = self.sa.query(UserGroupRepoToPerm)\
592 .filter(UsersGroupRepoToPerm.repository == repo)\
588 .filter(UserGroupRepoToPerm.repository == repo)\
593 .filter(UsersGroupRepoToPerm.users_group == group_name)\
589 .filter(UserGroupRepoToPerm.users_group == group_name)\
594 .scalar()
590 .scalar()
595 if obj:
591 if obj:
596 self.sa.delete(obj)
592 self.sa.delete(obj)
@@ -26,7 +26,7 b''
26
26
27 import logging
27 import logging
28 from rhodecode.model import BaseModel
28 from rhodecode.model import BaseModel
29 from rhodecode.model.db import UserRepoToPerm, UsersGroupRepoToPerm, \
29 from rhodecode.model.db import UserRepoToPerm, UserGroupRepoToPerm, \
30 Permission
30 Permission
31
31
32 log = logging.getLogger(__name__)
32 log = logging.getLogger(__name__)
@@ -64,9 +64,9 b' class RepositoryPermissionModel(BaseMode'
64 self.sa.delete(current)
64 self.sa.delete(current)
65
65
66 def get_users_group_permission(self, repository, users_group):
66 def get_users_group_permission(self, repository, users_group):
67 return UsersGroupRepoToPerm.query() \
67 return UserGroupRepoToPerm.query() \
68 .filter(UsersGroupRepoToPerm.users_group == users_group) \
68 .filter(UserGroupRepoToPerm.users_group == users_group) \
69 .filter(UsersGroupRepoToPerm.repository == repository) \
69 .filter(UserGroupRepoToPerm.repository == repository) \
70 .scalar()
70 .scalar()
71
71
72 def update_users_group_permission(self, repository, users_group,
72 def update_users_group_permission(self, repository, users_group,
@@ -77,7 +77,7 b' class RepositoryPermissionModel(BaseMode'
77 if not current.permission is permission:
77 if not current.permission is permission:
78 current.permission = permission
78 current.permission = permission
79 else:
79 else:
80 p = UsersGroupRepoToPerm()
80 p = UserGroupRepoToPerm()
81 p.users_group = users_group
81 p.users_group = users_group
82 p.repository = repository
82 p.repository = repository
83 p.permission = permission
83 p.permission = permission
@@ -3,7 +3,7 b''
3 rhodecode.model.user_group
3 rhodecode.model.user_group
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~
5
5
6 users groups model for RhodeCode
6 repo group model for RhodeCode
7
7
8 :created_on: Jan 25, 2011
8 :created_on: Jan 25, 2011
9 :author: marcink
9 :author: marcink
@@ -33,7 +33,7 b' from rhodecode.lib.utils2 import LazyPro'
33
33
34 from rhodecode.model import BaseModel
34 from rhodecode.model import BaseModel
35 from rhodecode.model.db import RepoGroup, RhodeCodeUi, UserRepoGroupToPerm, \
35 from rhodecode.model.db import RepoGroup, RhodeCodeUi, UserRepoGroupToPerm, \
36 User, Permission, UsersGroupRepoGroupToPerm, UsersGroup, Repository
36 User, Permission, UserGroupRepoGroupToPerm, UserGroup, Repository
37
37
38 log = logging.getLogger(__name__)
38 log = logging.getLogger(__name__)
39
39
@@ -43,8 +43,8 b' class ReposGroupModel(BaseModel):'
43 cls = RepoGroup
43 cls = RepoGroup
44
44
45 def __get_users_group(self, users_group):
45 def __get_users_group(self, users_group):
46 return self._get_instance(UsersGroup, users_group,
46 return self._get_instance(UserGroup, users_group,
47 callback=UsersGroup.get_by_group_name)
47 callback=UserGroup.get_by_group_name)
48
48
49 def _get_repos_group(self, repos_group):
49 def _get_repos_group(self, repos_group):
50 return self._get_instance(RepoGroup, repos_group,
50 return self._get_instance(RepoGroup, repos_group,
@@ -79,7 +79,7 b' class ReposGroupModel(BaseModel):'
79
79
80 def __create_group(self, group_name):
80 def __create_group(self, group_name):
81 """
81 """
82 makes repositories group on filesystem
82 makes repository group on filesystem
83
83
84 :param repo_name:
84 :param repo_name:
85 :param parent_id:
85 :param parent_id:
@@ -218,7 +218,7 b' class ReposGroupModel(BaseModel):'
218 if member_type == 'user':
218 if member_type == 'user':
219 # this updates also current one if found
219 # this updates also current one if found
220 _set_perm_user(obj, user=member, perm=perm)
220 _set_perm_user(obj, user=member, perm=perm)
221 ## set for users group
221 ## set for user group
222 else:
222 else:
223 _set_perm_group(obj, users_group=member, perm=perm)
223 _set_perm_group(obj, users_group=member, perm=perm)
224 # set new permissions
224 # set new permissions
@@ -289,11 +289,11 b' class ReposGroupModel(BaseModel):'
289 def delete_permission(self, repos_group, obj, obj_type, recursive):
289 def delete_permission(self, repos_group, obj, obj_type, recursive):
290 """
290 """
291 Revokes permission for repos_group for given obj(user or users_group),
291 Revokes permission for repos_group for given obj(user or users_group),
292 obj_type can be user or users group
292 obj_type can be user or user group
293
293
294 :param repos_group:
294 :param repos_group:
295 :param obj: user or users group id
295 :param obj: user or user group id
296 :param obj_type: user or users group type
296 :param obj_type: user or user group type
297 :param recursive: recurse to all children of group
297 :param recursive: recurse to all children of group
298 """
298 """
299 from rhodecode.model.repo import RepoModel
299 from rhodecode.model.repo import RepoModel
@@ -327,7 +327,7 b' class ReposGroupModel(BaseModel):'
327
327
328 def grant_user_permission(self, repos_group, user, perm):
328 def grant_user_permission(self, repos_group, user, perm):
329 """
329 """
330 Grant permission for user on given repositories group, or update
330 Grant permission for user on given repository group, or update
331 existing one if found
331 existing one if found
332
332
333 :param repos_group: Instance of ReposGroup, repositories_group_id,
333 :param repos_group: Instance of ReposGroup, repositories_group_id,
@@ -356,7 +356,7 b' class ReposGroupModel(BaseModel):'
356
356
357 def revoke_user_permission(self, repos_group, user):
357 def revoke_user_permission(self, repos_group, user):
358 """
358 """
359 Revoke permission for user on given repositories group
359 Revoke permission for user on given repository group
360
360
361 :param repos_group: Instance of ReposGroup, repositories_group_id,
361 :param repos_group: Instance of ReposGroup, repositories_group_id,
362 or repositories_group name
362 or repositories_group name
@@ -376,13 +376,13 b' class ReposGroupModel(BaseModel):'
376
376
377 def grant_users_group_permission(self, repos_group, group_name, perm):
377 def grant_users_group_permission(self, repos_group, group_name, perm):
378 """
378 """
379 Grant permission for users group on given repositories group, or update
379 Grant permission for user group on given repository group, or update
380 existing one if found
380 existing one if found
381
381
382 :param repos_group: Instance of ReposGroup, repositories_group_id,
382 :param repos_group: Instance of ReposGroup, repositories_group_id,
383 or repositories_group name
383 or repositories_group name
384 :param group_name: Instance of UserGroup, users_group_id,
384 :param group_name: Instance of UserGroup, users_group_id,
385 or users group name
385 or user group name
386 :param perm: Instance of Permission, or permission_name
386 :param perm: Instance of Permission, or permission_name
387 """
387 """
388 repos_group = self._get_repos_group(repos_group)
388 repos_group = self._get_repos_group(repos_group)
@@ -390,14 +390,14 b' class ReposGroupModel(BaseModel):'
390 permission = self._get_perm(perm)
390 permission = self._get_perm(perm)
391
391
392 # check if we have that permission already
392 # check if we have that permission already
393 obj = self.sa.query(UsersGroupRepoGroupToPerm)\
393 obj = self.sa.query(UserGroupRepoGroupToPerm)\
394 .filter(UsersGroupRepoGroupToPerm.group == repos_group)\
394 .filter(UserGroupRepoGroupToPerm.group == repos_group)\
395 .filter(UsersGroupRepoGroupToPerm.users_group == group_name)\
395 .filter(UserGroupRepoGroupToPerm.users_group == group_name)\
396 .scalar()
396 .scalar()
397
397
398 if obj is None:
398 if obj is None:
399 # create new
399 # create new
400 obj = UsersGroupRepoGroupToPerm()
400 obj = UserGroupRepoGroupToPerm()
401
401
402 obj.group = repos_group
402 obj.group = repos_group
403 obj.users_group = group_name
403 obj.users_group = group_name
@@ -407,19 +407,19 b' class ReposGroupModel(BaseModel):'
407
407
408 def revoke_users_group_permission(self, repos_group, group_name):
408 def revoke_users_group_permission(self, repos_group, group_name):
409 """
409 """
410 Revoke permission for users group on given repositories group
410 Revoke permission for user group on given repository group
411
411
412 :param repos_group: Instance of ReposGroup, repositories_group_id,
412 :param repos_group: Instance of ReposGroup, repositories_group_id,
413 or repositories_group name
413 or repositories_group name
414 :param group_name: Instance of UserGroup, users_group_id,
414 :param group_name: Instance of UserGroup, users_group_id,
415 or users group name
415 or user group name
416 """
416 """
417 repos_group = self._get_repos_group(repos_group)
417 repos_group = self._get_repos_group(repos_group)
418 group_name = self.__get_users_group(group_name)
418 group_name = self.__get_users_group(group_name)
419
419
420 obj = self.sa.query(UsersGroupRepoGroupToPerm)\
420 obj = self.sa.query(UserGroupRepoGroupToPerm)\
421 .filter(UsersGroupRepoGroupToPerm.group == repos_group)\
421 .filter(UserGroupRepoGroupToPerm.group == repos_group)\
422 .filter(UsersGroupRepoGroupToPerm.users_group == group_name)\
422 .filter(UserGroupRepoGroupToPerm.users_group == group_name)\
423 .scalar()
423 .scalar()
424 if obj:
424 if obj:
425 self.sa.delete(obj)
425 self.sa.delete(obj)
@@ -291,9 +291,7 b' class ScmModel(BaseModel):'
291 if all_groups is None:
291 if all_groups is None:
292 all_groups = RepoGroup.query()\
292 all_groups = RepoGroup.query()\
293 .filter(RepoGroup.group_parent_id == None).all()
293 .filter(RepoGroup.group_parent_id == None).all()
294 group_iter = GroupList(all_groups)
294 return [x for x in GroupList(all_groups)]
295
296 return group_iter
297
295
298 def mark_for_invalidation(self, repo_name):
296 def mark_for_invalidation(self, repo_name):
299 """
297 """
@@ -37,11 +37,12 b' from rhodecode.lib.utils2 import safe_un'
37 from rhodecode.lib.caching_query import FromCache
37 from rhodecode.lib.caching_query import FromCache
38 from rhodecode.model import BaseModel
38 from rhodecode.model import BaseModel
39 from rhodecode.model.db import User, UserRepoToPerm, Repository, Permission, \
39 from rhodecode.model.db import User, UserRepoToPerm, Repository, Permission, \
40 UserToPerm, UsersGroupRepoToPerm, UsersGroupToPerm, UsersGroupMember, \
40 UserToPerm, UserGroupRepoToPerm, UserGroupToPerm, UserGroupMember, \
41 Notification, RepoGroup, UserRepoGroupToPerm, UsersGroupRepoGroupToPerm, \
41 Notification, RepoGroup, UserRepoGroupToPerm, UserGroupRepoGroupToPerm, \
42 UserEmailMap, UserIpMap
42 UserEmailMap, UserIpMap
43 from rhodecode.lib.exceptions import DefaultUserException, \
43 from rhodecode.lib.exceptions import DefaultUserException, \
44 UserOwnsReposException
44 UserOwnsReposException
45 from rhodecode.model.meta import Session
45
46
46
47
47 log = logging.getLogger(__name__)
48 log = logging.getLogger(__name__)
@@ -316,11 +317,61 b' class UserModel(BaseModel):'
316
317
317 def reset_password_link(self, data):
318 def reset_password_link(self, data):
318 from rhodecode.lib.celerylib import tasks, run_task
319 from rhodecode.lib.celerylib import tasks, run_task
319 run_task(tasks.send_password_link, data['email'])
320 from rhodecode.model.notification import EmailNotificationModel
321 user_email = data['email']
322 try:
323 user = User.get_by_email(user_email)
324 if user:
325 log.debug('password reset user found %s' % user)
326 link = url('reset_password_confirmation', key=user.api_key,
327 qualified=True)
328 reg_type = EmailNotificationModel.TYPE_PASSWORD_RESET
329 body = EmailNotificationModel().get_email_tmpl(reg_type,
330 **{'user': user.short_contact,
331 'reset_url': link})
332 log.debug('sending email')
333 run_task(tasks.send_email, user_email,
334 _("password reset link"), body, body)
335 log.info('send new password mail to %s' % user_email)
336 else:
337 log.debug("password reset email %s not found" % user_email)
338 except:
339 log.error(traceback.format_exc())
340 return False
341
342 return True
320
343
321 def reset_password(self, data):
344 def reset_password(self, data):
322 from rhodecode.lib.celerylib import tasks, run_task
345 from rhodecode.lib.celerylib import tasks, run_task
323 run_task(tasks.reset_user_password, data['email'])
346 from rhodecode.lib import auth
347 user_email = data['email']
348 try:
349 try:
350 user = User.get_by_email(user_email)
351 new_passwd = auth.PasswordGenerator().gen_password(8,
352 auth.PasswordGenerator.ALPHABETS_BIG_SMALL)
353 if user:
354 user.password = auth.get_crypt_password(new_passwd)
355 user.api_key = auth.generate_api_key(user.username)
356 Session().add(user)
357 Session().commit()
358 log.info('change password for %s' % user_email)
359 if new_passwd is None:
360 raise Exception('unable to generate new password')
361 except:
362 log.error(traceback.format_exc())
363 Session().rollback()
364
365 run_task(tasks.send_email, user_email,
366 _('Your new password'),
367 _('Your new RhodeCode password:%s') % (new_passwd))
368 log.info('send new password mail to %s' % user_email)
369
370 except:
371 log.error('Failed to update user password')
372 log.error(traceback.format_exc())
373
374 return True
324
375
325 def fill_data(self, auth_user, user_id=None, api_key=None):
376 def fill_data(self, auth_user, user_id=None, api_key=None):
326 """
377 """
@@ -413,7 +464,7 b' class UserModel(BaseModel):'
413 p = 'repository.admin'
464 p = 'repository.admin'
414 user.permissions[RK][r_k] = p
465 user.permissions[RK][r_k] = p
415
466
416 # repositories groups
467 # repository groups
417 for perm in default_repo_groups_perms:
468 for perm in default_repo_groups_perms:
418 rg_k = perm.UserRepoGroupToPerm.group.group_name
469 rg_k = perm.UserRepoGroupToPerm.group.group_name
419 p = 'group.admin'
470 p = 'group.admin'
@@ -446,7 +497,7 b' class UserModel(BaseModel):'
446
497
447 user.permissions[RK][r_k] = p
498 user.permissions[RK][r_k] = p
448
499
449 # defaults for repositories groups taken from default user permission
500 # defaults for repository groups taken from default user permission
450 # on given group
501 # on given group
451 for perm in default_repo_groups_perms:
502 for perm in default_repo_groups_perms:
452 rg_k = perm.UserRepoGroupToPerm.group.group_name
503 rg_k = perm.UserRepoGroupToPerm.group.group_name
@@ -461,13 +512,13 b' class UserModel(BaseModel):'
461 'hg.create.none', 'hg.create.repository'])
512 'hg.create.none', 'hg.create.repository'])
462
513
463 # USER GROUPS comes first
514 # USER GROUPS comes first
464 # users group global permissions
515 # user group global permissions
465 user_perms_from_users_groups = self.sa.query(UsersGroupToPerm)\
516 user_perms_from_users_groups = self.sa.query(UserGroupToPerm)\
466 .options(joinedload(UsersGroupToPerm.permission))\
517 .options(joinedload(UserGroupToPerm.permission))\
467 .join((UsersGroupMember, UsersGroupToPerm.users_group_id ==
518 .join((UserGroupMember, UserGroupToPerm.users_group_id ==
468 UsersGroupMember.users_group_id))\
519 UserGroupMember.users_group_id))\
469 .filter(UsersGroupMember.user_id == uid)\
520 .filter(UserGroupMember.user_id == uid)\
470 .order_by(UsersGroupToPerm.users_group_id)\
521 .order_by(UserGroupToPerm.users_group_id)\
471 .all()
522 .all()
472 #need to group here by groups since user can be in more than one group
523 #need to group here by groups since user can be in more than one group
473 _grouped = [[x, list(y)] for x, y in
524 _grouped = [[x, list(y)] for x, y in
@@ -508,21 +559,21 b' class UserModel(BaseModel):'
508 # permission should be selected based on selected method
559 # permission should be selected based on selected method
509 #======================================================================
560 #======================================================================
510
561
511 # users group for repositories permissions
562 # user group for repositories permissions
512 user_repo_perms_from_users_groups = \
563 user_repo_perms_from_users_groups = \
513 self.sa.query(UsersGroupRepoToPerm, Permission, Repository,)\
564 self.sa.query(UserGroupRepoToPerm, Permission, Repository,)\
514 .join((Repository, UsersGroupRepoToPerm.repository_id ==
565 .join((Repository, UserGroupRepoToPerm.repository_id ==
515 Repository.repo_id))\
566 Repository.repo_id))\
516 .join((Permission, UsersGroupRepoToPerm.permission_id ==
567 .join((Permission, UserGroupRepoToPerm.permission_id ==
517 Permission.permission_id))\
568 Permission.permission_id))\
518 .join((UsersGroupMember, UsersGroupRepoToPerm.users_group_id ==
569 .join((UserGroupMember, UserGroupRepoToPerm.users_group_id ==
519 UsersGroupMember.users_group_id))\
570 UserGroupMember.users_group_id))\
520 .filter(UsersGroupMember.user_id == uid)\
571 .filter(UserGroupMember.user_id == uid)\
521 .all()
572 .all()
522
573
523 multiple_counter = collections.defaultdict(int)
574 multiple_counter = collections.defaultdict(int)
524 for perm in user_repo_perms_from_users_groups:
575 for perm in user_repo_perms_from_users_groups:
525 r_k = perm.UsersGroupRepoToPerm.repository.repo_name
576 r_k = perm.UserGroupRepoToPerm.repository.repo_name
526 multiple_counter[r_k] += 1
577 multiple_counter[r_k] += 1
527 p = perm.Permission.permission_name
578 p = perm.Permission.permission_name
528 cur_perm = user.permissions[RK][r_k]
579 cur_perm = user.permissions[RK][r_k]
@@ -559,27 +610,27 b' class UserModel(BaseModel):'
559 user.permissions[RK][r_k] = p
610 user.permissions[RK][r_k] = p
560
611
561 #======================================================================
612 #======================================================================
562 # !! PERMISSIONS FOR REPOSITORIES GROUPS !!
613 # !! PERMISSIONS FOR REPOSITORY GROUPS !!
563 #======================================================================
614 #======================================================================
564 #======================================================================
615 #======================================================================
565 # check if user is part of user groups for this repository groups and
616 # check if user is part of user groups for this repository groups and
566 # fill in his permission from it. _choose_perm decides of which
617 # fill in his permission from it. _choose_perm decides of which
567 # permission should be selected based on selected method
618 # permission should be selected based on selected method
568 #======================================================================
619 #======================================================================
569 # users group for repo groups permissions
620 # user group for repo groups permissions
570 user_repo_group_perms_from_users_groups = \
621 user_repo_group_perms_from_users_groups = \
571 self.sa.query(UsersGroupRepoGroupToPerm, Permission, RepoGroup)\
622 self.sa.query(UserGroupRepoGroupToPerm, Permission, RepoGroup)\
572 .join((RepoGroup, UsersGroupRepoGroupToPerm.group_id == RepoGroup.group_id))\
623 .join((RepoGroup, UserGroupRepoGroupToPerm.group_id == RepoGroup.group_id))\
573 .join((Permission, UsersGroupRepoGroupToPerm.permission_id
624 .join((Permission, UserGroupRepoGroupToPerm.permission_id
574 == Permission.permission_id))\
625 == Permission.permission_id))\
575 .join((UsersGroupMember, UsersGroupRepoGroupToPerm.users_group_id
626 .join((UserGroupMember, UserGroupRepoGroupToPerm.users_group_id
576 == UsersGroupMember.users_group_id))\
627 == UserGroupMember.users_group_id))\
577 .filter(UsersGroupMember.user_id == uid)\
628 .filter(UserGroupMember.user_id == uid)\
578 .all()
629 .all()
579
630
580 multiple_counter = collections.defaultdict(int)
631 multiple_counter = collections.defaultdict(int)
581 for perm in user_repo_group_perms_from_users_groups:
632 for perm in user_repo_group_perms_from_users_groups:
582 g_k = perm.UsersGroupRepoGroupToPerm.group.group_name
633 g_k = perm.UserGroupRepoGroupToPerm.group.group_name
583 multiple_counter[g_k] += 1
634 multiple_counter[g_k] += 1
584 p = perm.Permission.permission_name
635 p = perm.Permission.permission_name
585 cur_perm = user.permissions[GK][g_k]
636 cur_perm = user.permissions[GK][g_k]
@@ -3,7 +3,7 b''
3 rhodecode.model.users_group
3 rhodecode.model.users_group
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
5
5
6 users group model for RhodeCode
6 user group model for RhodeCode
7
7
8 :created_on: Oct 1, 2011
8 :created_on: Oct 1, 2011
9 :author: nvinot
9 :author: nvinot
@@ -28,33 +28,33 b' import logging'
28 import traceback
28 import traceback
29
29
30 from rhodecode.model import BaseModel
30 from rhodecode.model import BaseModel
31 from rhodecode.model.db import UsersGroupMember, UsersGroup,\
31 from rhodecode.model.db import UserGroupMember, UserGroup,\
32 UsersGroupRepoToPerm, Permission, UsersGroupToPerm, User
32 UserGroupRepoToPerm, Permission, UserGroupToPerm, User
33 from rhodecode.lib.exceptions import UsersGroupsAssignedException
33 from rhodecode.lib.exceptions import UserGroupsAssignedException
34
34
35 log = logging.getLogger(__name__)
35 log = logging.getLogger(__name__)
36
36
37
37
38 class UsersGroupModel(BaseModel):
38 class UserGroupModel(BaseModel):
39
39
40 cls = UsersGroup
40 cls = UserGroup
41
41
42 def __get_users_group(self, users_group):
42 def __get_users_group(self, users_group):
43 return self._get_instance(UsersGroup, users_group,
43 return self._get_instance(UserGroup, users_group,
44 callback=UsersGroup.get_by_group_name)
44 callback=UserGroup.get_by_group_name)
45
45
46 def get(self, users_group_id, cache=False):
46 def get(self, users_group_id, cache=False):
47 return UsersGroup.get(users_group_id)
47 return UserGroup.get(users_group_id)
48
48
49 def get_group(self, users_group):
49 def get_group(self, users_group):
50 return self.__get_users_group(users_group)
50 return self.__get_users_group(users_group)
51
51
52 def get_by_name(self, name, cache=False, case_insensitive=False):
52 def get_by_name(self, name, cache=False, case_insensitive=False):
53 return UsersGroup.get_by_group_name(name, cache, case_insensitive)
53 return UserGroup.get_by_group_name(name, cache, case_insensitive)
54
54
55 def create(self, name, active=True):
55 def create(self, name, active=True):
56 try:
56 try:
57 new = UsersGroup()
57 new = UserGroup()
58 new.users_group_name = name
58 new.users_group_name = name
59 new.users_group_active = active
59 new.users_group_active = active
60 self.sa.add(new)
60 self.sa.add(new)
@@ -76,7 +76,7 b' class UsersGroupModel(BaseModel):'
76 if v:
76 if v:
77 v = [v] if isinstance(v, basestring) else v
77 v = [v] if isinstance(v, basestring) else v
78 for u_id in set(v):
78 for u_id in set(v):
79 member = UsersGroupMember(users_group.users_group_id, u_id)
79 member = UserGroupMember(users_group.users_group_id, u_id)
80 members_list.append(member)
80 members_list.append(member)
81 setattr(users_group, 'members', members_list)
81 setattr(users_group, 'members', members_list)
82 setattr(users_group, k, v)
82 setattr(users_group, k, v)
@@ -99,11 +99,11 b' class UsersGroupModel(BaseModel):'
99 users_group = self.__get_users_group(users_group)
99 users_group = self.__get_users_group(users_group)
100
100
101 # check if this group is not assigned to repo
101 # check if this group is not assigned to repo
102 assigned_groups = UsersGroupRepoToPerm.query()\
102 assigned_groups = UserGroupRepoToPerm.query()\
103 .filter(UsersGroupRepoToPerm.users_group == users_group).all()
103 .filter(UserGroupRepoToPerm.users_group == users_group).all()
104
104
105 if assigned_groups and force is False:
105 if assigned_groups and force is False:
106 raise UsersGroupsAssignedException('RepoGroup assigned to %s' %
106 raise UserGroupsAssignedException('RepoGroup assigned to %s' %
107 assigned_groups)
107 assigned_groups)
108
108
109 self.sa.delete(users_group)
109 self.sa.delete(users_group)
@@ -121,7 +121,7 b' class UsersGroupModel(BaseModel):'
121 return True
121 return True
122
122
123 try:
123 try:
124 users_group_member = UsersGroupMember()
124 users_group_member = UserGroupMember()
125 users_group_member.user = user
125 users_group_member.user = user
126 users_group_member.users_group = users_group
126 users_group_member.users_group = users_group
127
127
@@ -160,23 +160,23 b' class UsersGroupModel(BaseModel):'
160 users_group = self.__get_users_group(users_group)
160 users_group = self.__get_users_group(users_group)
161 perm = self._get_perm(perm)
161 perm = self._get_perm(perm)
162
162
163 return UsersGroupToPerm.query()\
163 return UserGroupToPerm.query()\
164 .filter(UsersGroupToPerm.users_group == users_group)\
164 .filter(UserGroupToPerm.users_group == users_group)\
165 .filter(UsersGroupToPerm.permission == perm).scalar() is not None
165 .filter(UserGroupToPerm.permission == perm).scalar() is not None
166
166
167 def grant_perm(self, users_group, perm):
167 def grant_perm(self, users_group, perm):
168 users_group = self.__get_users_group(users_group)
168 users_group = self.__get_users_group(users_group)
169 perm = self._get_perm(perm)
169 perm = self._get_perm(perm)
170
170
171 # if this permission is already granted skip it
171 # if this permission is already granted skip it
172 _perm = UsersGroupToPerm.query()\
172 _perm = UserGroupToPerm.query()\
173 .filter(UsersGroupToPerm.users_group == users_group)\
173 .filter(UserGroupToPerm.users_group == users_group)\
174 .filter(UsersGroupToPerm.permission == perm)\
174 .filter(UserGroupToPerm.permission == perm)\
175 .scalar()
175 .scalar()
176 if _perm:
176 if _perm:
177 return
177 return
178
178
179 new = UsersGroupToPerm()
179 new = UserGroupToPerm()
180 new.users_group = users_group
180 new.users_group = users_group
181 new.permission = perm
181 new.permission = perm
182 self.sa.add(new)
182 self.sa.add(new)
@@ -185,8 +185,8 b' class UsersGroupModel(BaseModel):'
185 users_group = self.__get_users_group(users_group)
185 users_group = self.__get_users_group(users_group)
186 perm = self._get_perm(perm)
186 perm = self._get_perm(perm)
187
187
188 obj = UsersGroupToPerm.query()\
188 obj = UserGroupToPerm.query()\
189 .filter(UsersGroupToPerm.users_group == users_group)\
189 .filter(UserGroupToPerm.users_group == users_group)\
190 .filter(UsersGroupToPerm.permission == perm).scalar()
190 .filter(UserGroupToPerm.permission == perm).scalar()
191 if obj:
191 if obj:
192 self.sa.delete(obj)
192 self.sa.delete(obj)
@@ -16,7 +16,7 b' from formencode.validators import ('
16 from rhodecode.lib.compat import OrderedSet
16 from rhodecode.lib.compat import OrderedSet
17 from rhodecode.lib import ipaddr
17 from rhodecode.lib import ipaddr
18 from rhodecode.lib.utils import repo_name_slug
18 from rhodecode.lib.utils import repo_name_slug
19 from rhodecode.model.db import RepoGroup, Repository, UsersGroup, User,\
19 from rhodecode.model.db import RepoGroup, Repository, UserGroup, User,\
20 ChangesetStatus
20 ChangesetStatus
21 from rhodecode.lib.exceptions import LdapImportError
21 from rhodecode.lib.exceptions import LdapImportError
22 from rhodecode.config.routing import ADMIN_PREFIX
22 from rhodecode.config.routing import ADMIN_PREFIX
@@ -129,13 +129,13 b' def ValidRepoUser():'
129 return _validator
129 return _validator
130
130
131
131
132 def ValidUsersGroup(edit=False, old_data={}):
132 def ValidUserGroup(edit=False, old_data={}):
133 class _validator(formencode.validators.FancyValidator):
133 class _validator(formencode.validators.FancyValidator):
134 messages = {
134 messages = {
135 'invalid_group': _(u'Invalid users group name'),
135 'invalid_group': _(u'Invalid user group name'),
136 'group_exist': _(u'Users group "%(usersgroup)s" already exists'),
136 'group_exist': _(u'User group "%(usergroup)s" already exists'),
137 'invalid_usersgroup_name':
137 'invalid_usergroup_name':
138 _(u'users group name may only contain alphanumeric '
138 _(u'user group name may only contain alphanumeric '
139 'characters underscores, periods or dashes and must begin '
139 'characters underscores, periods or dashes and must begin '
140 'with alphanumeric character')
140 'with alphanumeric character')
141 }
141 }
@@ -150,19 +150,19 b' def ValidUsersGroup(edit=False, old_data'
150 old_ugname = None
150 old_ugname = None
151 if edit:
151 if edit:
152 old_id = old_data.get('users_group_id')
152 old_id = old_data.get('users_group_id')
153 old_ugname = UsersGroup.get(old_id).users_group_name
153 old_ugname = UserGroup.get(old_id).users_group_name
154
154
155 if old_ugname != value or not edit:
155 if old_ugname != value or not edit:
156 is_existing_group = UsersGroup.get_by_group_name(value,
156 is_existing_group = UserGroup.get_by_group_name(value,
157 case_insensitive=True)
157 case_insensitive=True)
158 if is_existing_group:
158 if is_existing_group:
159 msg = M(self, 'group_exist', state, usersgroup=value)
159 msg = M(self, 'group_exist', state, usergroup=value)
160 raise formencode.Invalid(msg, value, state,
160 raise formencode.Invalid(msg, value, state,
161 error_dict=dict(users_group_name=msg)
161 error_dict=dict(users_group_name=msg)
162 )
162 )
163
163
164 if re.match(r'^[a-zA-Z0-9]{1}[a-zA-Z0-9\-\_\.]+$', value) is None:
164 if re.match(r'^[a-zA-Z0-9]{1}[a-zA-Z0-9\-\_\.]+$', value) is None:
165 msg = M(self, 'invalid_usersgroup_name', state)
165 msg = M(self, 'invalid_usergroup_name', state)
166 raise formencode.Invalid(msg, value, state,
166 raise formencode.Invalid(msg, value, state,
167 error_dict=dict(users_group_name=msg)
167 error_dict=dict(users_group_name=msg)
168 )
168 )
@@ -317,7 +317,7 b' def ValidRepoName(edit=False, old_data={'
317 _(u'Repository named %(repo)s already exists'),
317 _(u'Repository named %(repo)s already exists'),
318 'repository_in_group_exists': _(u'Repository "%(repo)s" already '
318 'repository_in_group_exists': _(u'Repository "%(repo)s" already '
319 'exists in group "%(group)s"'),
319 'exists in group "%(group)s"'),
320 'same_group_exists': _(u'Repositories group with name "%(repo)s" '
320 'same_group_exists': _(u'Repository group with name "%(repo)s" '
321 'already exists')
321 'already exists')
322 }
322 }
323
323
@@ -547,7 +547,7 b" def ValidPerms(type_='repo'):"
547 class _validator(formencode.validators.FancyValidator):
547 class _validator(formencode.validators.FancyValidator):
548 messages = {
548 messages = {
549 'perm_new_member_name':
549 'perm_new_member_name':
550 _(u'This username or users group name is not valid')
550 _(u'This username or user group name is not valid')
551 }
551 }
552
552
553 def to_python(self, value, state):
553 def to_python(self, value, state):
@@ -604,9 +604,9 b" def ValidPerms(type_='repo'):"
604 .filter(User.active == True)\
604 .filter(User.active == True)\
605 .filter(User.username == k).one()
605 .filter(User.username == k).one()
606 if t is 'users_group':
606 if t is 'users_group':
607 self.user_db = UsersGroup.query()\
607 self.user_db = UserGroup.query()\
608 .filter(UsersGroup.users_group_active == True)\
608 .filter(UserGroup.users_group_active == True)\
609 .filter(UsersGroup.users_group_name == k).one()
609 .filter(UserGroup.users_group_name == k).one()
610
610
611 except Exception:
611 except Exception:
612 log.exception('Updated permission failed')
612 log.exception('Updated permission failed')
@@ -160,56 +160,48 b' div.options a {'
160 .top-left-rounded-corner {
160 .top-left-rounded-corner {
161 -webkit-border-top-left-radius: 8px;
161 -webkit-border-top-left-radius: 8px;
162 -khtml-border-radius-topleft: 8px;
162 -khtml-border-radius-topleft: 8px;
163 -moz-border-radius-topleft: 8px;
164 border-top-left-radius: 8px;
163 border-top-left-radius: 8px;
165 }
164 }
166
165
167 .top-right-rounded-corner {
166 .top-right-rounded-corner {
168 -webkit-border-top-right-radius: 8px;
167 -webkit-border-top-right-radius: 8px;
169 -khtml-border-radius-topright: 8px;
168 -khtml-border-radius-topright: 8px;
170 -moz-border-radius-topright: 8px;
171 border-top-right-radius: 8px;
169 border-top-right-radius: 8px;
172 }
170 }
173
171
174 .bottom-left-rounded-corner {
172 .bottom-left-rounded-corner {
175 -webkit-border-bottom-left-radius: 8px;
173 -webkit-border-bottom-left-radius: 8px;
176 -khtml-border-radius-bottomleft: 8px;
174 -khtml-border-radius-bottomleft: 8px;
177 -moz-border-radius-bottomleft: 8px;
178 border-bottom-left-radius: 8px;
175 border-bottom-left-radius: 8px;
179 }
176 }
180
177
181 .bottom-right-rounded-corner {
178 .bottom-right-rounded-corner {
182 -webkit-border-bottom-right-radius: 8px;
179 -webkit-border-bottom-right-radius: 8px;
183 -khtml-border-radius-bottomright: 8px;
180 -khtml-border-radius-bottomright: 8px;
184 -moz-border-radius-bottomright: 8px;
185 border-bottom-right-radius: 8px;
181 border-bottom-right-radius: 8px;
186 }
182 }
187
183
188 .top-left-rounded-corner-mid {
184 .top-left-rounded-corner-mid {
189 -webkit-border-top-left-radius: 4px;
185 -webkit-border-top-left-radius: 4px;
190 -khtml-border-radius-topleft: 4px;
186 -khtml-border-radius-topleft: 4px;
191 -moz-border-radius-topleft: 4px;
192 border-top-left-radius: 4px;
187 border-top-left-radius: 4px;
193 }
188 }
194
189
195 .top-right-rounded-corner-mid {
190 .top-right-rounded-corner-mid {
196 -webkit-border-top-right-radius: 4px;
191 -webkit-border-top-right-radius: 4px;
197 -khtml-border-radius-topright: 4px;
192 -khtml-border-radius-topright: 4px;
198 -moz-border-radius-topright: 4px;
199 border-top-right-radius: 4px;
193 border-top-right-radius: 4px;
200 }
194 }
201
195
202 .bottom-left-rounded-corner-mid {
196 .bottom-left-rounded-corner-mid {
203 -webkit-border-bottom-left-radius: 4px;
197 -webkit-border-bottom-left-radius: 4px;
204 -khtml-border-radius-bottomleft: 4px;
198 -khtml-border-radius-bottomleft: 4px;
205 -moz-border-radius-bottomleft: 4px;
206 border-bottom-left-radius: 4px;
199 border-bottom-left-radius: 4px;
207 }
200 }
208
201
209 .bottom-right-rounded-corner-mid {
202 .bottom-right-rounded-corner-mid {
210 -webkit-border-bottom-right-radius: 4px;
203 -webkit-border-bottom-right-radius: 4px;
211 -khtml-border-radius-bottomright: 4px;
204 -khtml-border-radius-bottomright: 4px;
212 -moz-border-radius-bottomright: 4px;
213 border-bottom-right-radius: 4px;
205 border-bottom-right-radius: 4px;
214 }
206 }
215
207
@@ -244,12 +236,10 b' div:hover > a.permalink {'
244
236
245 #header {
237 #header {
246 }
238 }
247
248 #header ul#logged-user {
239 #header ul#logged-user {
249 margin-bottom: 5px !important;
240 margin-bottom: 5px !important;
250 -webkit-border-radius: 0px 0px 8px 8px;
241 -webkit-border-radius: 0px 0px 8px 8px;
251 -khtml-border-radius: 0px 0px 8px 8px;
242 -khtml-border-radius: 0px 0px 8px 8px;
252 -moz-border-radius: 0px 0px 8px 8px;
253 border-radius: 0px 0px 8px 8px;
243 border-radius: 0px 0px 8px 8px;
254 height: 37px;
244 height: 37px;
255 background-color: #003B76;
245 background-color: #003B76;
@@ -260,7 +250,7 b' div:hover > a.permalink {'
260 background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #003b76), color-stop(100%, #00376e) );
250 background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #003b76), color-stop(100%, #00376e) );
261 background-image: -webkit-linear-gradient(top, #003b76, #00376e);
251 background-image: -webkit-linear-gradient(top, #003b76, #00376e);
262 background-image: -o-linear-gradient(top, #003b76, #00376e);
252 background-image: -o-linear-gradient(top, #003b76, #00376e);
263 background-image: linear-gradient(top, #003b76, #00376e);
253 background-image: linear-gradient(to bottom, #003b76, #00376e);
264 filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#003b76',endColorstr='#00376e', GradientType=0 );
254 filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#003b76',endColorstr='#00376e', GradientType=0 );
265 box-shadow: 0 2px 2px rgba(0, 0, 0, 0.6);
255 box-shadow: 0 2px 2px rgba(0, 0, 0, 0.6);
266 }
256 }
@@ -314,19 +304,18 b' div:hover > a.permalink {'
314 background-color: #003B76;
304 background-color: #003B76;
315 opacity: 0.01;
305 opacity: 0.01;
316 cursor: pointer;
306 cursor: pointer;
317 min-height: 10px;
307 min-height: 10px;
318 width: 100% !important;
308 width: 100% !important;
319 -webkit-border-radius: 0px 0px 4px 4px;
309 -webkit-border-radius: 0px 0px 4px 4px;
320 -khtml-border-radius: 0px 0px 4px 4px;
310 -khtml-border-radius: 0px 0px 4px 4px;
321 -moz-border-radius: 0px 0px 4px 4px;
322 border-radius: 0px 0px 4px 4px;
311 border-radius: 0px 0px 4px 4px;
323 }
312 }
324
313
325 #header-dd:hover{
314 #header-dd:hover{
326 opacity: 0.2;
315 opacity: 0.2;
327 -webkit-transition: opacity 0.5s ease-in-out;
316 -webkit-transition: opacity 0.5s ease-in-out;
328 -moz-transition: opacity 0.5s ease-in-out;
317 -moz-transition: opacity 0.5s ease-in-out;
329 transition: opacity 0.5s ease-in-out;
318 transition: opacity 0.5s ease-in-out;
330 }
319 }
331
320
332 #header #header-inner {
321 #header #header-inner {
@@ -341,7 +330,7 b' div:hover > a.permalink {'
341 background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #003b76),color-stop(100%, #00376e) );
330 background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #003b76),color-stop(100%, #00376e) );
342 background-image: -webkit-linear-gradient(top, #003b76, #00376e);
331 background-image: -webkit-linear-gradient(top, #003b76, #00376e);
343 background-image: -o-linear-gradient(top, #003b76, #00376e);
332 background-image: -o-linear-gradient(top, #003b76, #00376e);
344 background-image: linear-gradient(top, #003b76, #00376e);
333 background-image: linear-gradient(to bottom, #003b76, #00376e);
345 filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#003b76',endColorstr='#00376e', GradientType=0 );
334 filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#003b76',endColorstr='#00376e', GradientType=0 );
346 margin: 0;
335 margin: 0;
347 padding: 0;
336 padding: 0;
@@ -349,17 +338,15 b' div:hover > a.permalink {'
349 box-shadow: 0 2px 2px rgba(0, 0, 0, 0.6);
338 box-shadow: 0 2px 2px rgba(0, 0, 0, 0.6);
350 -webkit-border-radius: 0px 0px 4px 4px;
339 -webkit-border-radius: 0px 0px 4px 4px;
351 -khtml-border-radius: 0px 0px 4px 4px;
340 -khtml-border-radius: 0px 0px 4px 4px;
352 -moz-border-radius: 0px 0px 4px 4px;
353 border-radius: 0px 0px 4px 4px;
341 border-radius: 0px 0px 4px 4px;
354 }
342 }
355 #header #header-inner.hover {
343 #header #header-inner.hover {
356 width: 100% !important;
344 width: 100% !important;
357 -webkit-border-radius: 0px 0px 0px 0px;
345 -webkit-border-radius: 0px 0px 0px 0px;
358 -khtml-border-radius: 0px 0px 0px 0px;
346 -khtml-border-radius: 0px 0px 0px 0px;
359 -moz-border-radius: 0px 0px 0px 0px;
360 border-radius: 0px 0px 0px 0px;
347 border-radius: 0px 0px 0px 0px;
361 position: fixed !important;
348 position: fixed !important;
362 z-index: 10000;
349 z-index: 10000;
363 }
350 }
364
351
365 .ie7 #header #header-inner.hover,
352 .ie7 #header #header-inner.hover,
@@ -439,7 +426,6 b' div:hover > a.permalink {'
439 padding: 0;
426 padding: 0;
440 -webkit-border-radius: 4px 4px 4px 4px;
427 -webkit-border-radius: 4px 4px 4px 4px;
441 -khtml-border-radius: 4px 4px 4px 4px;
428 -khtml-border-radius: 4px 4px 4px 4px;
442 -moz-border-radius: 4px 4px 4px 4px;
443 border-radius: 4px 4px 4px 4px;
429 border-radius: 4px 4px 4px 4px;
444 }
430 }
445
431
@@ -1096,7 +1082,6 b' tbody .yui-dt-editable { cursor: pointer'
1096 padding: 0 0 10px;
1082 padding: 0 0 10px;
1097 -webkit-border-radius: 4px 4px 4px 4px;
1083 -webkit-border-radius: 4px 4px 4px 4px;
1098 -khtml-border-radius: 4px 4px 4px 4px;
1084 -khtml-border-radius: 4px 4px 4px 4px;
1099 -moz-border-radius: 4px 4px 4px 4px;
1100 border-radius: 4px 4px 4px 4px;
1085 border-radius: 4px 4px 4px 4px;
1101 box-shadow: 0 2px 2px rgba(0, 0, 0, 0.6);
1086 box-shadow: 0 2px 2px rgba(0, 0, 0, 0.6);
1102 }
1087 }
@@ -1126,7 +1111,7 b' tbody .yui-dt-editable { cursor: pointer'
1126 background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #003b76), color-stop(100%, #00376e) );
1111 background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #003b76), color-stop(100%, #00376e) );
1127 background-image: -webkit-linear-gradient(top, #003b76, #00376e);
1112 background-image: -webkit-linear-gradient(top, #003b76, #00376e);
1128 background-image: -o-linear-gradient(top, #003b76, #00376e);
1113 background-image: -o-linear-gradient(top, #003b76, #00376e);
1129 background-image: linear-gradient(top, #003b76, #00376e);
1114 background-image: linear-gradient(to bottom, #003b76, #00376e);
1130 filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#003b76', endColorstr='#00376e', GradientType=0 );
1115 filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#003b76', endColorstr='#00376e', GradientType=0 );
1131 margin: 0 0 20px;
1116 margin: 0 0 20px;
1132 padding: 0;
1117 padding: 0;
@@ -1267,7 +1252,7 b' tbody .yui-dt-editable { cursor: pointer'
1267 background:-moz-linear-gradient(top,rgba(255,255,255,0),rgba(64,96,128,0.1));
1252 background:-moz-linear-gradient(top,rgba(255,255,255,0),rgba(64,96,128,0.1));
1268 background:-o-linear-gradient(top,rgba(255,255,255,0),rgba(64,96,128,0.1));
1253 background:-o-linear-gradient(top,rgba(255,255,255,0),rgba(64,96,128,0.1));
1269 background:-ms-linear-gradient(top,rgba(255,255,255,0),rgba(64,96,128,0.1));
1254 background:-ms-linear-gradient(top,rgba(255,255,255,0),rgba(64,96,128,0.1));
1270 background:linear-gradient(top,rgba(255,255,255,0),rgba(64,96,128,0.1));
1255 background:linear-gradient(to bottom,rgba(255,255,255,0),rgba(64,96,128,0.1));
1271
1256
1272 display: none;
1257 display: none;
1273 }
1258 }
@@ -1623,7 +1608,6 b' div.form div.fields div.field div.button'
1623 padding: 0;
1608 padding: 0;
1624 border: 1px solid #eee;
1609 border: 1px solid #eee;
1625 -webkit-border-radius: 4px;
1610 -webkit-border-radius: 4px;
1626 -moz-border-radius: 4px;
1627 border-radius: 4px;
1611 border-radius: 4px;
1628 }
1612 }
1629
1613
@@ -1949,7 +1933,6 b' div.form div.fields div.field div.button'
1949 margin-right: 1px;
1933 margin-right: 1px;
1950 -webkit-border-radius: 4px 4px 4px 4px;
1934 -webkit-border-radius: 4px 4px 4px 4px;
1951 -khtml-border-radius: 4px 4px 4px 4px;
1935 -khtml-border-radius: 4px 4px 4px 4px;
1952 -moz-border-radius: 4px 4px 4px 4px;
1953 border-radius: 4px 4px 4px 4px;
1936 border-radius: 4px 4px 4px 4px;
1954
1937
1955 border: solid 1px #9CF;
1938 border: solid 1px #9CF;
@@ -2027,12 +2010,11 b' a.metatag[tag="license"]:hover {'
2027 background-image : -webkit-gradient( linear, left top, left bottom, color-stop( 0%, #003b76), color-stop( 100%, #00376e));
2010 background-image : -webkit-gradient( linear, left top, left bottom, color-stop( 0%, #003b76), color-stop( 100%, #00376e));
2028 background-image : -webkit-linear-gradient( top, #003b76, #00376e));
2011 background-image : -webkit-linear-gradient( top, #003b76, #00376e));
2029 background-image : -o-linear-gradient( top, #003b76, #00376e));
2012 background-image : -o-linear-gradient( top, #003b76, #00376e));
2030 background-image : linear-gradient( top, #003b76, #00376e);
2013 background-image : linear-gradient(to bottom, #003b76, #00376e);
2031 filter :progid : DXImageTransform.Microsoft.gradient ( startColorstr = '#003b76', endColorstr = '#00376e', GradientType = 0);
2014 filter :progid : DXImageTransform.Microsoft.gradient ( startColorstr = '#003b76', endColorstr = '#00376e', GradientType = 0);
2032 box-shadow: 0 2px 2px rgba(0, 0, 0, 0.6);
2015 box-shadow: 0 2px 2px rgba(0, 0, 0, 0.6);
2033 -webkit-border-radius: 4px 4px 4px 4px;
2016 -webkit-border-radius: 4px 4px 4px 4px;
2034 -khtml-border-radius: 4px 4px 4px 4px;
2017 -khtml-border-radius: 4px 4px 4px 4px;
2035 -moz-border-radius: 4px 4px 4px 4px;
2036 border-radius: 4px 4px 4px 4px;
2018 border-radius: 4px 4px 4px 4px;
2037 }
2019 }
2038
2020
@@ -2063,7 +2045,7 b' a.metatag[tag="license"]:hover {'
2063 background-image : -webkit-gradient( linear, left top, left bottom, color-stop( 0%, #003b76), color-stop( 100%, #00376e));
2045 background-image : -webkit-gradient( linear, left top, left bottom, color-stop( 0%, #003b76), color-stop( 100%, #00376e));
2064 background-image : -webkit-linear-gradient( top, #003b76, #00376e));
2046 background-image : -webkit-linear-gradient( top, #003b76, #00376e));
2065 background-image : -o-linear-gradient( top, #003b76, #00376e));
2047 background-image : -o-linear-gradient( top, #003b76, #00376e));
2066 background-image : linear-gradient( top, #003b76, #00376e);
2048 background-image : linear-gradient(to bottom, #003b76, #00376e);
2067 filter : progid : DXImageTransform.Microsoft.gradient ( startColorstr = '#003b76', endColorstr = '#00376e', GradientType = 0);
2049 filter : progid : DXImageTransform.Microsoft.gradient ( startColorstr = '#003b76', endColorstr = '#00376e', GradientType = 0);
2068 margin: 0 auto;
2050 margin: 0 auto;
2069 padding: 0;
2051 padding: 0;
@@ -2147,13 +2129,12 b' a.metatag[tag="license"]:hover {'
2147 background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #003b76), color-stop(100%, #00376e) );
2129 background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #003b76), color-stop(100%, #00376e) );
2148 background-image: -webkit-linear-gradient(top, #003b76, #00376e);
2130 background-image: -webkit-linear-gradient(top, #003b76, #00376e);
2149 background-image: -o-linear-gradient(top, #003b76, #00376e);
2131 background-image: -o-linear-gradient(top, #003b76, #00376e);
2150 background-image: linear-gradient(top, #003b76, #00376e);
2132 background-image: linear-gradient(to bottom, #003b76, #00376e);
2151 filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#003b76', endColorstr='#00376e', GradientType=0 );
2133 filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#003b76', endColorstr='#00376e', GradientType=0 );
2152
2134
2153 z-index: 999;
2135 z-index: 999;
2154 -webkit-border-radius: 0px 0px 4px 4px;
2136 -webkit-border-radius: 0px 0px 4px 4px;
2155 -khtml-border-radius: 0px 0px 4px 4px;
2137 -khtml-border-radius: 0px 0px 4px 4px;
2156 -moz-border-radius: 0px 0px 4px 4px;
2157 border-radius: 0px 0px 4px 4px;
2138 border-radius: 0px 0px 4px 4px;
2158 box-shadow: 0 2px 2px rgba(0, 0, 0, 0.6);
2139 box-shadow: 0 2px 2px rgba(0, 0, 0, 0.6);
2159 }
2140 }
@@ -2213,7 +2194,7 b' a.metatag[tag="license"]:hover {'
2213 #quick_login .unread a {
2194 #quick_login .unread a {
2214 color: #FFFFFF;
2195 color: #FFFFFF;
2215 display: block;
2196 display: block;
2216 padding: 2px;
2197 padding: 2px;
2217 }
2198 }
2218 #quick_login .notifications a:hover,
2199 #quick_login .notifications a:hover,
2219 #quick_login .unread a:hover {
2200 #quick_login .unread a:hover {
@@ -2304,7 +2285,7 b' a.metatag[tag="license"]:hover {'
2304 background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #003b76), color-stop(100%, #00376e) );
2285 background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #003b76), color-stop(100%, #00376e) );
2305 background-image: -webkit-linear-gradient(top, #003b76, #00376e);
2286 background-image: -webkit-linear-gradient(top, #003b76, #00376e);
2306 background-image: -o-linear-gradient(top, #003b76, #00376e);
2287 background-image: -o-linear-gradient(top, #003b76, #00376e);
2307 background-image: linear-gradient(top, #003b76, #00376e);
2288 background-image: linear-gradient(to bottom, #003b76, #00376e);
2308 filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#003b76',
2289 filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#003b76',
2309 endColorstr='#00376e', GradientType=0 );
2290 endColorstr='#00376e', GradientType=0 );
2310 margin: 0 auto;
2291 margin: 0 auto;
@@ -2780,7 +2761,6 b' h3.files_location {'
2780 color: #444444;
2761 color: #444444;
2781 background: #FEA;
2762 background: #FEA;
2782 -webkit-border-radius: 0px 0px 0px 6px;
2763 -webkit-border-radius: 0px 0px 0px 6px;
2783 -moz-border-radius: 0px 0px 0px 6px;
2784 border-radius: 0px 0px 0px 6px;
2764 border-radius: 0px 0px 0px 6px;
2785 padding: 1px;
2765 padding: 1px;
2786 }
2766 }
@@ -2815,7 +2795,6 b' h3.files_location {'
2815 text-transform: uppercase;
2795 text-transform: uppercase;
2816 white-space: nowrap;
2796 white-space: nowrap;
2817 -webkit-border-radius: 3px;
2797 -webkit-border-radius: 3px;
2818 -moz-border-radius: 3px;
2819 border-radius: 3px;
2798 border-radius: 3px;
2820 margin-right: 2px;
2799 margin-right: 2px;
2821 }
2800 }
@@ -2841,7 +2820,6 b' h3.files_location {'
2841 color: #ffffff;
2820 color: #ffffff;
2842 white-space: nowrap;
2821 white-space: nowrap;
2843 -webkit-border-radius: 3px;
2822 -webkit-border-radius: 3px;
2844 -moz-border-radius: 3px;
2845 border-radius: 3px;
2823 border-radius: 3px;
2846 }
2824 }
2847 .right .logtags .branchtag a:hover, .logtags .branchtag a {
2825 .right .logtags .branchtag a:hover, .logtags .branchtag a {
@@ -2859,7 +2837,6 b' h3.files_location {'
2859 color: #ffffff;
2837 color: #ffffff;
2860 white-space: nowrap;
2838 white-space: nowrap;
2861 -webkit-border-radius: 3px;
2839 -webkit-border-radius: 3px;
2862 -moz-border-radius: 3px;
2863 border-radius: 3px;
2840 border-radius: 3px;
2864 }
2841 }
2865 .right .logtags .tagtag a:hover, .logtags .tagtag a {
2842 .right .logtags .tagtag a:hover, .logtags .tagtag a {
@@ -2878,7 +2855,6 b' h3.files_location {'
2878 text-transform: uppercase;
2855 text-transform: uppercase;
2879 white-space: nowrap;
2856 white-space: nowrap;
2880 -webkit-border-radius: 3px;
2857 -webkit-border-radius: 3px;
2881 -moz-border-radius: 3px;
2882 border-radius: 3px;
2858 border-radius: 3px;
2883 }
2859 }
2884 .right .logbooks .bookbook, .logbooks .bookbook a, .right .logtags .bookbook, .logtags .bookbook a {
2860 .right .logbooks .bookbook, .logbooks .bookbook a, .right .logtags .bookbook, .logtags .bookbook a {
@@ -2896,7 +2872,6 b' div.browserblock {'
2896 line-height: 125%;
2872 line-height: 125%;
2897 padding: 0;
2873 padding: 0;
2898 -webkit-border-radius: 6px 6px 0px 0px;
2874 -webkit-border-radius: 6px 6px 0px 0px;
2899 -moz-border-radius: 6px 6px 0px 0px;
2900 border-radius: 6px 6px 0px 0px;
2875 border-radius: 6px 6px 0px 0px;
2901 }
2876 }
2902
2877
@@ -3109,16 +3084,14 b' table.code-browser .submodule-dir {'
3109 border: 2px solid #003367;
3084 border: 2px solid #003367;
3110 font: 100% sans-serif;
3085 font: 100% sans-serif;
3111 width: auto;
3086 width: auto;
3112 opacity: 1px;
3087 opacity: 1;
3113 padding: 8px;
3088 padding: 8px;
3114
3089
3115 white-space: pre-wrap;
3090 white-space: pre-wrap;
3116 -webkit-border-radius: 8px 8px 8px 8px;
3091 -webkit-border-radius: 8px 8px 8px 8px;
3117 -khtml-border-radius: 8px 8px 8px 8px;
3092 -khtml-border-radius: 8px 8px 8px 8px;
3118 -moz-border-radius: 8px 8px 8px 8px;
3119 border-radius: 8px 8px 8px 8px;
3093 border-radius: 8px 8px 8px 8px;
3120 box-shadow: 0 2px 2px rgba(0, 0, 0, 0.6);
3094 box-shadow: 0 2px 2px rgba(0, 0, 0, 0.6);
3121 -moz-box-shadow: 0 2px 2px rgba(0, 0, 0, 0.6);
3122 -webkit-box-shadow: 0 2px 2px rgba(0, 0, 0, 0.6);
3095 -webkit-box-shadow: 0 2px 2px rgba(0, 0, 0, 0.6);
3123 }
3096 }
3124
3097
@@ -3130,12 +3103,11 b' table.code-browser .submodule-dir {'
3130 border: 2px solid #003367;
3103 border: 2px solid #003367;
3131 font: 100% sans-serif;
3104 font: 100% sans-serif;
3132 width: auto;
3105 width: auto;
3133 opacity: 1px;
3106 opacity: 1;
3134 padding: 8px;
3107 padding: 8px;
3135 white-space: pre-wrap;
3108 white-space: pre-wrap;
3136 -webkit-border-radius: 8px 8px 8px 8px;
3109 -webkit-border-radius: 8px 8px 8px 8px;
3137 -khtml-border-radius: 8px 8px 8px 8px;
3110 -khtml-border-radius: 8px 8px 8px 8px;
3138 -moz-border-radius: 8px 8px 8px 8px;
3139 border-radius: 8px 8px 8px 8px;
3111 border-radius: 8px 8px 8px 8px;
3140 box-shadow: 0 2px 2px rgba(0, 0, 0, 0.6);
3112 box-shadow: 0 2px 2px rgba(0, 0, 0, 0.6);
3141 }
3113 }
@@ -3182,7 +3154,6 b' table.code-browser .submodule-dir {'
3182 position: absolute;
3154 position: absolute;
3183 width: 100%;
3155 width: 100%;
3184 background: #000;
3156 background: #000;
3185 -moz-opacity: 0.1px;
3186 opacity: .10;
3157 opacity: .10;
3187 filter: alpha(opacity = 10);
3158 filter: alpha(opacity = 10);
3188 z-index: 9049;
3159 z-index: 9049;
@@ -3428,7 +3399,7 b' table.code-browser .submodule-dir {'
3428 background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #ee5f5b), color-stop(100%, #c43c35) );
3399 background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #ee5f5b), color-stop(100%, #c43c35) );
3429 background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35);
3400 background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35);
3430 background-image: -o-linear-gradient(top, #ee5f5b, #c43c35);
3401 background-image: -o-linear-gradient(top, #ee5f5b, #c43c35);
3431 background-image: linear-gradient(top, #ee5f5b, #c43c35);
3402 background-image: linear-gradient(to bottom, #ee5f5b, #c43c35);
3432 filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ee5f5b',endColorstr='#c43c35', GradientType=0 );
3403 filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ee5f5b',endColorstr='#c43c35', GradientType=0 );
3433 border-color: #c43c35 #c43c35 #882a25;
3404 border-color: #c43c35 #c43c35 #882a25;
3434 }
3405 }
@@ -3443,7 +3414,7 b' table.code-browser .submodule-dir {'
3443 background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #fceec1), color-stop(100%, #eedc94) );
3414 background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #fceec1), color-stop(100%, #eedc94) );
3444 background-image: -webkit-linear-gradient(top, #fceec1, #eedc94);
3415 background-image: -webkit-linear-gradient(top, #fceec1, #eedc94);
3445 background-image: -o-linear-gradient(top, #fceec1, #eedc94);
3416 background-image: -o-linear-gradient(top, #fceec1, #eedc94);
3446 background-image: linear-gradient(top, #fceec1, #eedc94);
3417 background-image: linear-gradient(to bottom, #fceec1, #eedc94);
3447 filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fceec1', endColorstr='#eedc94', GradientType=0 );
3418 filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fceec1', endColorstr='#eedc94', GradientType=0 );
3448 border-color: #eedc94 #eedc94 #e4c652;
3419 border-color: #eedc94 #eedc94 #e4c652;
3449 }
3420 }
@@ -3457,7 +3428,7 b' table.code-browser .submodule-dir {'
3457 background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #62c462), color-stop(100%, #57a957) );
3428 background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #62c462), color-stop(100%, #57a957) );
3458 background-image: -webkit-linear-gradient(top, #62c462, #57a957);
3429 background-image: -webkit-linear-gradient(top, #62c462, #57a957);
3459 background-image: -o-linear-gradient(top, #62c462, #57a957);
3430 background-image: -o-linear-gradient(top, #62c462, #57a957);
3460 background-image: linear-gradient(top, #62c462, #57a957);
3431 background-image: linear-gradient(to bottom, #62c462, #57a957);
3461 filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#62c462', endColorstr='#57a957', GradientType=0 );
3432 filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#62c462', endColorstr='#57a957', GradientType=0 );
3462 border-color: #57a957 #57a957 #3d773d;
3433 border-color: #57a957 #57a957 #3d773d;
3463 }
3434 }
@@ -3471,7 +3442,7 b' table.code-browser .submodule-dir {'
3471 background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #5bc0de), color-stop(100%, #339bb9) );
3442 background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #5bc0de), color-stop(100%, #339bb9) );
3472 background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9);
3443 background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9);
3473 background-image: -o-linear-gradient(top, #5bc0de, #339bb9);
3444 background-image: -o-linear-gradient(top, #5bc0de, #339bb9);
3474 background-image: linear-gradient(top, #5bc0de, #339bb9);
3445 background-image: linear-gradient(to bottom, #5bc0de, #339bb9);
3475 filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#5bc0de', endColorstr='#339bb9', GradientType=0 );
3446 filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#5bc0de', endColorstr='#339bb9', GradientType=0 );
3476 border-color: #339bb9 #339bb9 #22697d;
3447 border-color: #339bb9 #339bb9 #22697d;
3477 }
3448 }
@@ -3492,10 +3463,8 b' table.code-browser .submodule-dir {'
3492 border-width: 1px;
3463 border-width: 1px;
3493 border-style: solid;
3464 border-style: solid;
3494 -webkit-border-radius: 4px;
3465 -webkit-border-radius: 4px;
3495 -moz-border-radius: 4px;
3496 border-radius: 4px;
3466 border-radius: 4px;
3497 -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25);
3467 -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25);
3498 -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25);
3499 box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25);
3468 box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25);
3500 }
3469 }
3501
3470
@@ -3524,7 +3493,7 b' table#permissions_manage {'
3524
3493
3525 table#permissions_manage span.private_repo_msg {
3494 table#permissions_manage span.private_repo_msg {
3526 font-size: 0.8em;
3495 font-size: 0.8em;
3527 opacity: 0.6px;
3496 opacity: 0.6;
3528 }
3497 }
3529
3498
3530 table#permissions_manage td.private_repo_msg {
3499 table#permissions_manage td.private_repo_msg {
@@ -3543,14 +3512,12 b' div.gravatar {'
3543 line-height:0;
3512 line-height:0;
3544 -webkit-border-radius: 3px;
3513 -webkit-border-radius: 3px;
3545 -khtml-border-radius: 3px;
3514 -khtml-border-radius: 3px;
3546 -moz-border-radius: 3px;
3547 border-radius: 3px;
3515 border-radius: 3px;
3548 }
3516 }
3549
3517
3550 div.gravatar img {
3518 div.gravatar img {
3551 -webkit-border-radius: 2px;
3519 -webkit-border-radius: 2px;
3552 -khtml-border-radius: 2px;
3520 -khtml-border-radius: 2px;
3553 -moz-border-radius: 2px;
3554 border-radius: 2px;
3521 border-radius: 2px;
3555 }
3522 }
3556
3523
@@ -3586,7 +3553,7 b' div.gravatar img {'
3586 background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #F4F4F4),color-stop(100%, #DADADA) );
3553 background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #F4F4F4),color-stop(100%, #DADADA) );
3587 background-image: -webkit-linear-gradient(top, #F4F4F4, #DADADA) );
3554 background-image: -webkit-linear-gradient(top, #F4F4F4, #DADADA) );
3588 background-image: -o-linear-gradient(top, #F4F4F4, #DADADA) );
3555 background-image: -o-linear-gradient(top, #F4F4F4, #DADADA) );
3589 background-image: linear-gradient(top, #F4F4F4, #DADADA);
3556 background-image: linear-gradient(to bottom, #F4F4F4, #DADADA);
3590 filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#F4F4F4', endColorstr='#DADADA', GradientType=0);
3557 filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#F4F4F4', endColorstr='#DADADA', GradientType=0);
3591
3558
3592 border-top: 1px solid #DDD;
3559 border-top: 1px solid #DDD;
@@ -3598,7 +3565,6 b' div.gravatar img {'
3598 margin: 0px 3px 3px 0px;
3565 margin: 0px 3px 3px 0px;
3599 -webkit-border-radius: 4px 4px 4px 4px !important;
3566 -webkit-border-radius: 4px 4px 4px 4px !important;
3600 -khtml-border-radius: 4px 4px 4px 4px !important;
3567 -khtml-border-radius: 4px 4px 4px 4px !important;
3601 -moz-border-radius: 4px 4px 4px 4px !important;
3602 border-radius: 4px 4px 4px 4px !important;
3568 border-radius: 4px 4px 4px 4px !important;
3603 cursor: pointer !important;
3569 cursor: pointer !important;
3604 padding: 3px 3px 3px 3px;
3570 padding: 3px 3px 3px 3px;
@@ -3623,7 +3589,6 b' div.gravatar img {'
3623 margin: 0px 0px 3px -4px;
3589 margin: 0px 0px 3px -4px;
3624 -webkit-border-radius: 0px 4px 4px 0px !important;
3590 -webkit-border-radius: 0px 4px 4px 0px !important;
3625 -khtml-border-radius: 0px 4px 4px 0px !important;
3591 -khtml-border-radius: 0px 4px 4px 0px !important;
3626 -moz-border-radius: 0px 4px 4px 0px !important;
3627 border-radius: 0px 4px 4px 0px !important;
3592 border-radius: 0px 4px 4px 0px !important;
3628 width: 100px;
3593 width: 100px;
3629 text-align: center;
3594 text-align: center;
@@ -3642,7 +3607,7 b' div.gravatar img {'
3642 }
3607 }
3643
3608
3644 .ui-btn.disabled:hover {
3609 .ui-btn.disabled:hover {
3645 background-position:none;
3610 background-position: 0;
3646 color: #999;
3611 color: #999;
3647 text-decoration: none;
3612 text-decoration: none;
3648 box-shadow: none !important;
3613 box-shadow: none !important;
@@ -3658,7 +3623,7 b' div.gravatar img {'
3658 background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #ee5f5b), color-stop(100%, #c43c35));
3623 background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #ee5f5b), color-stop(100%, #c43c35));
3659 background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35);
3624 background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35);
3660 background-image: -o-linear-gradient(top, #ee5f5b, #c43c35);
3625 background-image: -o-linear-gradient(top, #ee5f5b, #c43c35);
3661 background-image: linear-gradient(top, #ee5f5b, #c43c35);
3626 background-image: linear-gradient(to bottom, #ee5f5b, #c43c35);
3662 filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ee5f5b', endColorstr='#c43c35', GradientType=0);
3627 filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ee5f5b', endColorstr='#c43c35', GradientType=0);
3663 border-color: #c43c35 #c43c35 #882a25;
3628 border-color: #c43c35 #c43c35 #882a25;
3664 border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
3629 border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
@@ -3675,7 +3640,7 b' div.gravatar img {'
3675 background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #5bc0de), color-stop(100%, #339bb9));
3640 background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #5bc0de), color-stop(100%, #339bb9));
3676 background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9);
3641 background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9);
3677 background-image: -o-linear-gradient(top, #5bc0de, #339bb9);
3642 background-image: -o-linear-gradient(top, #5bc0de, #339bb9);
3678 background-image: linear-gradient(top, #5bc0de, #339bb9);
3643 background-image: linear-gradient(to bottom, #5bc0de, #339bb9);
3679 filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#5bc0de', endColorstr='#339bb9', GradientType=0);
3644 filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#5bc0de', endColorstr='#339bb9', GradientType=0);
3680 border-color: #339bb9 #339bb9 #22697d;
3645 border-color: #339bb9 #339bb9 #22697d;
3681 border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
3646 border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
@@ -3690,7 +3655,7 b' div.gravatar img {'
3690 background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #62c462), color-stop(100%, #57a957));
3655 background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #62c462), color-stop(100%, #57a957));
3691 background-image: -webkit-linear-gradient(top, #62c462, #57a957);
3656 background-image: -webkit-linear-gradient(top, #62c462, #57a957);
3692 background-image: -o-linear-gradient(top, #62c462, #57a957);
3657 background-image: -o-linear-gradient(top, #62c462, #57a957);
3693 background-image: linear-gradient(top, #62c462, #57a957);
3658 background-image: linear-gradient(to bottom, #62c462, #57a957);
3694 filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#62c462', endColorstr='#57a957', GradientType=0);
3659 filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#62c462', endColorstr='#57a957', GradientType=0);
3695 border-color: #57a957 #57a957 #3d773d;
3660 border-color: #57a957 #57a957 #3d773d;
3696 border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
3661 border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
@@ -3864,7 +3829,6 b' input.ui-button {'
3864 padding: 6px 12px;
3829 padding: 6px 12px;
3865 -webkit-border-radius: 4px 4px 4px 4px;
3830 -webkit-border-radius: 4px 4px 4px 4px;
3866 -khtml-border-radius: 4px 4px 4px 4px;
3831 -khtml-border-radius: 4px 4px 4px 4px;
3867 -moz-border-radius: 4px 4px 4px 4px;
3868 border-radius: 4px 4px 4px 4px;
3832 border-radius: 4px 4px 4px 4px;
3869 box-shadow: 0 1px 0 #ececec;
3833 box-shadow: 0 1px 0 #ececec;
3870 cursor: pointer;
3834 cursor: pointer;
@@ -3996,6 +3960,10 b' div.form div.fields div.field div.highli'
3996 padding: 0;
3960 padding: 0;
3997 }
3961 }
3998
3962
3963 #login div.form div.fields div.field div.input input.large {
3964 width: 250px;
3965 }
3966
3999 #login div.form div.fields div.field div.checkbox, #register div.form div.fields div.field div.checkbox {
3967 #login div.form div.fields div.field div.checkbox, #register div.form div.fields div.field div.checkbox {
4000 margin: 0 0 0 184px;
3968 margin: 0 0 0 184px;
4001 padding: 0;
3969 padding: 0;
@@ -4038,7 +4006,6 b' div#legend_container table td, div#legen'
4038 .q_filter_box {
4006 .q_filter_box {
4039 -webkit-box-shadow: rgba(0,0,0,0.07) 0 1px 2px inset;
4007 -webkit-box-shadow: rgba(0,0,0,0.07) 0 1px 2px inset;
4040 -webkit-border-radius: 4px;
4008 -webkit-border-radius: 4px;
4041 -moz-border-radius: 4px;
4042 border-radius: 4px;
4009 border-radius: 4px;
4043 border: 0 none;
4010 border: 0 none;
4044 color: #AAAAAA;
4011 color: #AAAAAA;
@@ -4188,7 +4155,6 b' div.readme .readme_box pre {'
4188 overflow: auto;
4155 overflow: auto;
4189 -webkit-box-shadow: rgba(0,0,0,0.07) 0 1px 2px inset;
4156 -webkit-box-shadow: rgba(0,0,0,0.07) 0 1px 2px inset;
4190 -webkit-border-radius: 3px;
4157 -webkit-border-radius: 3px;
4191 -moz-border-radius: 3px;
4192 border-radius: 3px;
4158 border-radius: 3px;
4193 }
4159 }
4194
4160
@@ -4290,7 +4256,6 b' div.rst-block pre {'
4290 overflow: auto;
4256 overflow: auto;
4291 -webkit-box-shadow: rgba(0,0,0,0.07) 0 1px 2px inset;
4257 -webkit-box-shadow: rgba(0,0,0,0.07) 0 1px 2px inset;
4292 -webkit-border-radius: 3px;
4258 -webkit-border-radius: 3px;
4293 -moz-border-radius: 3px;
4294 border-radius: 3px;
4259 border-radius: 3px;
4295 }
4260 }
4296
4261
@@ -4304,7 +4269,6 b' div.rst-block pre {'
4304 border: 1px solid #ddd;
4269 border: 1px solid #ddd;
4305 margin-top: 10px;
4270 margin-top: 10px;
4306 -webkit-border-radius: 4px;
4271 -webkit-border-radius: 4px;
4307 -moz-border-radius: 4px;
4308 border-radius: 4px;
4272 border-radius: 4px;
4309 }
4273 }
4310
4274
@@ -4354,7 +4318,6 b' div.rst-block pre {'
4354 .comment-form .clearfix {
4318 .comment-form .clearfix {
4355 background: #EEE;
4319 background: #EEE;
4356 -webkit-border-radius: 4px;
4320 -webkit-border-radius: 4px;
4357 -moz-border-radius: 4px;
4358 border-radius: 4px;
4321 border-radius: 4px;
4359 padding: 10px;
4322 padding: 10px;
4360 }
4323 }
@@ -4440,7 +4403,6 b' form.comment-form {'
4440 .comment-inline-form .clearfix {
4403 .comment-inline-form .clearfix {
4441 background: #EEE;
4404 background: #EEE;
4442 -webkit-border-radius: 4px;
4405 -webkit-border-radius: 4px;
4443 -moz-border-radius: 4px;
4444 border-radius: 4px;
4406 border-radius: 4px;
4445 padding: 5px;
4407 padding: 5px;
4446 }
4408 }
@@ -4517,7 +4479,6 b' form.comment-inline-form {'
4517 .inline-comments .comment {
4479 .inline-comments .comment {
4518 border: 1px solid #ddd;
4480 border: 1px solid #ddd;
4519 -webkit-border-radius: 4px;
4481 -webkit-border-radius: 4px;
4520 -moz-border-radius: 4px;
4521 border-radius: 4px;
4482 border-radius: 4px;
4522 margin: 3px 3px 5px 5px;
4483 margin: 3px 3px 5px 5px;
4523 background-color: #FAFAFA;
4484 background-color: #FAFAFA;
@@ -4584,7 +4545,6 b' form.comment-inline-form {'
4584 background-color: #DEDEDE !important;
4545 background-color: #DEDEDE !important;
4585 border-radius: 4px !important;
4546 border-radius: 4px !important;
4586 -webkit-border-radius: 4px !important;
4547 -webkit-border-radius: 4px !important;
4587 -moz-border-radius: 4px !important;
4588 }
4548 }
4589
4549
4590 .notification-header {
4550 .notification-header {
@@ -4609,7 +4569,6 b' form.comment-inline-form {'
4609 .notification-table {
4569 .notification-table {
4610 border: 1px solid #ccc;
4570 border: 1px solid #ccc;
4611 -webkit-border-radius: 6px 6px 6px 6px;
4571 -webkit-border-radius: 6px 6px 6px 6px;
4612 -moz-border-radius: 6px 6px 6px 6px;
4613 border-radius: 6px 6px 6px 6px;
4572 border-radius: 6px 6px 6px 6px;
4614 clear: both;
4573 clear: both;
4615 margin: 0px 20px 0px 20px;
4574 margin: 0px 20px 0px 20px;
@@ -4660,7 +4619,6 b' PULL REQUESTS'
4660 text-transform: uppercase;
4619 text-transform: uppercase;
4661 white-space: nowrap;
4620 white-space: nowrap;
4662 -webkit-border-radius: 3px;
4621 -webkit-border-radius: 3px;
4663 -moz-border-radius: 3px;
4664 border-radius: 3px;
4622 border-radius: 3px;
4665 }
4623 }
4666
4624
@@ -4698,6 +4656,24 b' PULL REQUESTS'
4698 /*****************************************************************************
4656 /*****************************************************************************
4699 DIFFS CSS
4657 DIFFS CSS
4700 ******************************************************************************/
4658 ******************************************************************************/
4659 .diff-collapse{
4660 text-align: center;
4661 margin-bottom: -15px;
4662 }
4663 .diff-collapse-button{
4664 cursor: pointer;
4665 color: #666;
4666 font-size: 16px;
4667 }
4668 .diff-container {
4669
4670 }
4671
4672 .diff-container.hidden{
4673 display: none;
4674 overflow: hidden;
4675 }
4676
4701
4677
4702 div.diffblock {
4678 div.diffblock {
4703 overflow: auto;
4679 overflow: auto;
@@ -4709,7 +4685,6 b' div.diffblock {'
4709 /* new */
4685 /* new */
4710 line-height: 125%;
4686 line-height: 125%;
4711 -webkit-border-radius: 6px 6px 0px 0px;
4687 -webkit-border-radius: 6px 6px 0px 0px;
4712 -moz-border-radius: 6px 6px 0px 0px;
4713 border-radius: 6px 6px 0px 0px;
4688 border-radius: 6px 6px 0px 0px;
4714 }
4689 }
4715 div.diffblock.margined {
4690 div.diffblock.margined {
@@ -4787,12 +4762,13 b' div.diffblock pre.raw {'
4787 table.code-difftable {
4762 table.code-difftable {
4788 border-collapse: collapse;
4763 border-collapse: collapse;
4789 width: 99%;
4764 width: 99%;
4765 border-radius: 0px !important;
4790 }
4766 }
4791 table.code-difftable td {
4767 table.code-difftable td {
4792 padding: 0 !important;
4768 padding: 0 !important;
4793 background: none !important;
4769 background: none !important;
4794 border:0 !important;
4770 border:0 !important;
4795 vertical-align: none !important;
4771 vertical-align: baseline !important
4796 }
4772 }
4797 table.code-difftable .context {
4773 table.code-difftable .context {
4798 background:none repeat scroll 0 0 #DDE7EF;
4774 background:none repeat scroll 0 0 #DDE7EF;
@@ -4887,3 +4863,8 b' table.code-difftable .code pre {'
4887 div.comment:target>.comment-wrapp {
4863 div.comment:target>.comment-wrapp {
4888 border: solid 2px #ee0 !important;
4864 border: solid 2px #ee0 !important;
4889 }
4865 }
4866
4867 .lineno:target a {
4868 border: solid 2px #ee0 !important;
4869 margin: -2px;
4870 }
@@ -302,12 +302,25 b' var pyroutes = (function() {'
302 }
302 }
303 if (matchlist.hasOwnProperty(route_name)) {
303 if (matchlist.hasOwnProperty(route_name)) {
304 var route = matchlist[route_name];
304 var route = matchlist[route_name];
305 // param substitution
305 for(var i=0; i < route[1].length; i++) {
306 for(var i=0; i < route[1].length; i++) {
306
307
307 if (!params.hasOwnProperty(route[1][i]))
308 if (!params.hasOwnProperty(route[1][i]))
308 throw new Error(route[1][i] + ' missing in "' + route_name + '" route generation');
309 throw new Error(route[1][i] + ' missing in "' + route_name + '" route generation');
309 }
310 }
310 result = sprintf(route[0], params);
311 result = sprintf(route[0], params);
312
313 var ret = [];
314 //extra params => GET
315 for(param in params){
316 if (route[1].indexOf(param) == -1){
317 ret.push(encodeURIComponent(param) + "=" + encodeURIComponent(params[param]));
318 }
319 }
320 var _parts = ret.join("&");
321 if(_parts){
322 result = result +'?'+ _parts
323 }
311 }
324 }
312
325
313 return result;
326 return result;
@@ -1289,7 +1302,7 b' var MembersAutoComplete = function (divi'
1289 return matches;
1302 return matches;
1290 };
1303 };
1291
1304
1292 // Define a custom search function for the DataSource of usersGroups
1305 // Define a custom search function for the DataSource of userGroups
1293 var matchGroups = function (sQuery) {
1306 var matchGroups = function (sQuery) {
1294 // Case insensitive matching
1307 // Case insensitive matching
1295 var query = sQuery.toLowerCase();
1308 var query = sQuery.toLowerCase();
@@ -1707,7 +1720,7 b' var PullRequestAutoComplete = function ('
1707 return matches;
1720 return matches;
1708 };
1721 };
1709
1722
1710 // Define a custom search function for the DataSource of usersGroups
1723 // Define a custom search function for the DataSource of userGroups
1711 var matchGroups = function (sQuery) {
1724 var matchGroups = function (sQuery) {
1712 // Case insensitive matching
1725 // Case insensitive matching
1713 var query = sQuery.toLowerCase();
1726 var query = sQuery.toLowerCase();
@@ -2149,3 +2162,26 b' var MultiSelectWidget = function(selecte'
2149 });
2162 });
2150 }
2163 }
2151 }
2164 }
2165
2166
2167 // global hooks after DOM is loaded
2168
2169 YUE.onDOMReady(function(){
2170 YUE.on(YUQ('.diff-collapse-button'), 'click', function(e){
2171 var button = e.currentTarget;
2172 var t = YUD.get(button).getAttribute('target');
2173 console.log(t);
2174 if(YUD.hasClass(t, 'hidden')){
2175 YUD.removeClass(t, 'hidden');
2176 YUD.get(button).innerHTML = "&uarr; {0} &uarr;".format(_TM['collapse diff']);
2177 }
2178 else if(!YUD.hasClass(t, 'hidden')){
2179 YUD.addClass(t, 'hidden');
2180 YUD.get(button).innerHTML = "&darr; {0} &darr;".format(_TM['expand diff']);
2181 }
2182 });
2183
2184
2185
2186 });
2187
@@ -39,7 +39,12 b''
39 <span id="${c.notification.notification_id}" class="delete-notification delete_icon action"></span>
39 <span id="${c.notification.notification_id}" class="delete-notification delete_icon action"></span>
40 </div>
40 </div>
41 </div>
41 </div>
42 <div class="notification-body">${h.rst_w_mentions(c.notification.body)}</div>
42 <div class="notification-body">
43 <div class="notification-subject">${h.literal(c.notification.subject)}</div>
44 %if c.notification.body:
45 ${h.rst_w_mentions(c.notification.body)}
46 %endif
47 </div>
43 </div>
48 </div>
44 </div>
49 </div>
45 </div>
50 </div>
@@ -59,7 +59,7 b''
59 ${h.checkbox('overwrite_default_group','true')}
59 ${h.checkbox('overwrite_default_group','true')}
60 <label for="overwrite_default_group">
60 <label for="overwrite_default_group">
61 <span class="tooltip"
61 <span class="tooltip"
62 title="${h.tooltip(_('All default permissions on each repository group will be reset to choosen permission, note that all custom default permission on repositories group will be lost'))}">
62 title="${h.tooltip(_('All default permissions on each repository group will be reset to choosen permission, note that all custom default permission on repository groups will be lost'))}">
63 ${_('overwrite existing settings')}</span> </label>
63 ${_('overwrite existing settings')}</span> </label>
64
64
65 </div>
65 </div>
@@ -38,7 +38,7 b''
38 %endif
38 %endif
39 %endfor
39 %endfor
40
40
41 ## USERS GROUPS
41 ## USER GROUPS
42 %for g2p in c.repo_info.users_group_to_perm:
42 %for g2p in c.repo_info.users_group_to_perm:
43 <tr id="id${id(g2p.users_group.users_group_name)}">
43 <tr id="id${id(g2p.users_group.users_group_name)}">
44 <td>${h.radio('g_perm_%s' % g2p.users_group.users_group_name,'repository.none')}</td>
44 <td>${h.radio('g_perm_%s' % g2p.users_group.users_group_name,'repository.none')}</td>
@@ -54,7 +54,7 b''
54 %endif
54 %endif
55 </td>
55 </td>
56 <td>
56 <td>
57 <span class="delete_icon action_button" onclick="ajaxActionUsersGroup(${g2p.users_group.users_group_id},'${'id%s'%id(g2p.users_group.users_group_name)}')">
57 <span class="delete_icon action_button" onclick="ajaxActionUserGroup(${g2p.users_group.users_group_id},'${'id%s'%id(g2p.users_group.users_group_name)}')">
58 ${_('revoke')}
58 ${_('revoke')}
59 </span>
59 </span>
60 </td>
60 </td>
@@ -101,7 +101,7 b' function ajaxActionUser(user_id, field_i'
101 var request = YAHOO.util.Connect.asyncRequest('POST', sUrl, callback, postData);
101 var request = YAHOO.util.Connect.asyncRequest('POST', sUrl, callback, postData);
102 };
102 };
103
103
104 function ajaxActionUsersGroup(users_group_id,field_id){
104 function ajaxActionUserGroup(users_group_id,field_id){
105 var sUrl = "${h.url('delete_repo_users_group',repo_name=c.repo_name)}";
105 var sUrl = "${h.url('delete_repo_users_group',repo_name=c.repo_name)}";
106 var callback = {
106 var callback = {
107 success:function(o){
107 success:function(o){
@@ -109,7 +109,7 b' function ajaxActionUsersGroup(users_grou'
109 tr.parentNode.removeChild(tr);
109 tr.parentNode.removeChild(tr);
110 },
110 },
111 failure:function(o){
111 failure:function(o){
112 alert("${_('Failed to remove users group')}");
112 alert("${_('Failed to remove user group')}");
113 },
113 },
114 };
114 };
115 var postData = '_method=delete&users_group_id='+users_group_id;
115 var postData = '_method=delete&users_group_id='+users_group_id;
@@ -40,7 +40,7 b''
40 </tr>
40 </tr>
41 %endfor
41 %endfor
42
42
43 ## USERS GROUPS
43 ## USER GROUPS
44 %for g2p in c.repos_group.users_group_to_perm:
44 %for g2p in c.repos_group.users_group_to_perm:
45 <tr id="id${id(g2p.users_group.users_group_name)}">
45 <tr id="id${id(g2p.users_group.users_group_name)}">
46 <td>${h.radio('g_perm_%s' % g2p.users_group.users_group_name,'group.none')}</td>
46 <td>${h.radio('g_perm_%s' % g2p.users_group.users_group_name,'group.none')}</td>
@@ -51,7 +51,7 b''
51 <img class="perm-gravatar" src="${h.url('/images/icons/group.png')}"/>${g2p.users_group.users_group_name}
51 <img class="perm-gravatar" src="${h.url('/images/icons/group.png')}"/>${g2p.users_group.users_group_name}
52 </td>
52 </td>
53 <td>
53 <td>
54 <span class="delete_icon action_button" onclick="ajaxActionUsersGroup(${g2p.users_group.users_group_id},'${'id%s'%id(g2p.users_group.users_group_name)}')">
54 <span class="delete_icon action_button" onclick="ajaxActionUserGroup(${g2p.users_group.users_group_id},'${'id%s'%id(g2p.users_group.users_group_name)}')">
55 ${_('revoke')}
55 ${_('revoke')}
56 </span>
56 </span>
57 </td>
57 </td>
@@ -105,7 +105,7 b' function ajaxActionUser(user_id, field_i'
105 var request = YAHOO.util.Connect.asyncRequest('POST', sUrl, callback, postData);
105 var request = YAHOO.util.Connect.asyncRequest('POST', sUrl, callback, postData);
106 };
106 };
107
107
108 function ajaxActionUsersGroup(users_group_id,field_id){
108 function ajaxActionUserGroup(users_group_id,field_id){
109 var sUrl = "${h.url('delete_repos_group_users_group_perm',group_name=c.repos_group.group_name)}";
109 var sUrl = "${h.url('delete_repos_group_users_group_perm',group_name=c.repos_group.group_name)}";
110 var callback = {
110 var callback = {
111 success:function(o){
111 success:function(o){
@@ -113,7 +113,7 b' function ajaxActionUsersGroup(users_grou'
113 tr.parentNode.removeChild(tr);
113 tr.parentNode.removeChild(tr);
114 },
114 },
115 failure:function(o){
115 failure:function(o){
116 alert("${_('Failed to remove users group')}");
116 alert("${_('Failed to remove user group')}");
117 },
117 },
118 };
118 };
119 var recursive = YUD.get('recursive').checked;
119 var recursive = YUD.get('recursive').checked;
@@ -2,14 +2,14 b''
2 <%inherit file="/base/base.html"/>
2 <%inherit file="/base/base.html"/>
3
3
4 <%def name="title()">
4 <%def name="title()">
5 ${_('Repositories groups administration')} - ${c.rhodecode_name}
5 ${_('Repository groups administration')} - ${c.rhodecode_name}
6 </%def>
6 </%def>
7
7
8
8
9 <%def name="breadcrumbs_links()">
9 <%def name="breadcrumbs_links()">
10 ${h.link_to(_('Admin'),h.url('admin_home'))}
10 ${h.link_to(_('Admin'),h.url('admin_home'))}
11 &raquo;
11 &raquo;
12 ${_('repositories groups')}
12 ${_('repository groups')}
13 </%def>
13 </%def>
14 <%def name="page_nav()">
14 <%def name="page_nav()">
15 ${self.menu('admin')}
15 ${self.menu('admin')}
@@ -48,7 +48,7 b''
48 <tr>
48 <tr>
49 <td>
49 <td>
50 <div style="white-space: nowrap">
50 <div style="white-space: nowrap">
51 <img class="icon" alt="${_('Repositories group')}" src="${h.url('/images/icons/database_link.png')}"/>
51 <img class="icon" alt="${_('Repository group')}" src="${h.url('/images/icons/database_link.png')}"/>
52 ${h.link_to(h.literal(' &raquo; '.join(map(h.safe_unicode,[g.name for g in gr.parents+[gr]]))), url('repos_group_home',group_name=gr.group_name))}
52 ${h.link_to(h.literal(' &raquo; '.join(map(h.safe_unicode,[g.name for g in gr.parents+[gr]]))), url('repos_group_home',group_name=gr.group_name))}
53 </div>
53 </div>
54 </td>
54 </td>
@@ -69,7 +69,7 b''
69
69
70 </table>
70 </table>
71 % else:
71 % else:
72 ${_('There are no repositories groups yet')}
72 ${_('There are no repository groups yet')}
73 % endif
73 % endif
74
74
75 </div>
75 </div>
@@ -64,7 +64,7 b''
64 <div class="checkboxes">
64 <div class="checkboxes">
65 <div class="checkbox">
65 <div class="checkbox">
66 ${h.checkbox('full_index',True)}
66 ${h.checkbox('full_index',True)}
67 <label for="full_index">${_('build from scratch')}</label>
67 <label for="full_index">${_('Build from scratch')}</label>
68 </div>
68 </div>
69 </div>
69 </div>
70 </div>
70 </div>
@@ -85,7 +85,7 b''
85
85
86 <div class="field">
86 <div class="field">
87 <div class="label">
87 <div class="label">
88 <label for="rhodecode_title">${_('Application name')}:</label>
88 <label for="rhodecode_title">${_('Site branding')}:</label>
89 </div>
89 </div>
90 <div class="input">
90 <div class="input">
91 ${h.text('rhodecode_title',size=30)}
91 ${h.text('rhodecode_title',size=30)}
@@ -94,7 +94,7 b''
94
94
95 <div class="field">
95 <div class="field">
96 <div class="label">
96 <div class="label">
97 <label for="rhodecode_realm">${_('Realm text')}:</label>
97 <label for="rhodecode_realm">${_('HTTP authentication realm')}:</label>
98 </div>
98 </div>
99 <div class="input">
99 <div class="input">
100 ${h.text('rhodecode_realm',size=30)}
100 ${h.text('rhodecode_realm',size=30)}
@@ -103,7 +103,7 b''
103
103
104 <div class="field">
104 <div class="field">
105 <div class="label">
105 <div class="label">
106 <label for="rhodecode_ga_code">${_('GA code')}:</label>
106 <label for="rhodecode_ga_code">${_('Google Analytics code')}:</label>
107 </div>
107 </div>
108 <div class="input">
108 <div class="input">
109 ${h.text('rhodecode_ga_code',size=30)}
109 ${h.text('rhodecode_ga_code',size=30)}
@@ -40,12 +40,12 b''
40 </div>
40 </div>
41 <div class="field">
41 <div class="field">
42 <div class="label">
42 <div class="label">
43 <label>${_('API key')}</label> ${c.user.api_key}
43 <label>${_('API key')}:</label> ${c.user.api_key}
44 </div>
44 </div>
45 </div>
45 </div>
46 <div class="field">
46 <div class="field">
47 <div class="label">
47 <div class="label">
48 <label>${_('Your IP')}</label> ${c.perm_user.ip_addr or "?"}
48 <label>${_('Current IP')}:</label> ${c.perm_user.ip_addr or "?"}
49 </div>
49 </div>
50 </div>
50 </div>
51 <div class="fields">
51 <div class="fields">
@@ -102,6 +102,7 b''
102 </div>
102 </div>
103
103
104 <script type="text/javascript">
104 <script type="text/javascript">
105 pyroutes.register('admin_settings_my_pullrequests', "${url('admin_settings_my_pullrequests')}", []);
105
106
106 var show_perms = function(e){
107 var show_perms = function(e){
107 YUD.addClass('show_perms', 'current');
108 YUD.addClass('show_perms', 'current');
@@ -145,8 +146,15 b' var show_pullrequests = function(e){'
145 YUD.setStyle('pullrequests_container','display','');
146 YUD.setStyle('pullrequests_container','display','');
146 YUD.setStyle('q_filter','display','none');
147 YUD.setStyle('q_filter','display','none');
147
148
148 var url = "${h.url('admin_settings_my_pullrequests')}";
149 var url = pyroutes.url('admin_settings_my_pullrequests');
149 ypjax(url, 'pullrequests_container');
150 if(YUD.get('show_closed') && YUD.get('show_closed').checked) {
151 var url = pyroutes.url('admin_settings_my_pullrequests', {'pr_show_closed': '1'});
152 }
153 ypjax(url, 'pullrequests_container', function(){
154 YUE.on('show_closed','change',function (e) {
155 show_pullrequests(e);
156 });
157 });
150 }
158 }
151 YUE.on('show_pullrequests','click',function(e){
159 YUE.on('show_pullrequests','click',function(e){
152 show_pullrequests(e)
160 show_pullrequests(e)
@@ -270,6 +278,7 b' function table_renderer(data){'
270 clearTimeout(filterTimeout);
278 clearTimeout(filterTimeout);
271 filterTimeout = setTimeout(updateFilter,600);
279 filterTimeout = setTimeout(updateFilter,600);
272 });
280 });
281
273 }
282 }
274 </script>
283 </script>
275 </%def>
284 </%def>
@@ -1,4 +1,8 b''
1
1 %if c.show_closed:
2 ${h.checkbox('show_closed',checked="checked", label=_('Show closed pull requests'))}
3 %else:
4 ${h.checkbox('show_closed',label=_('Show closed pull requests'))}
5 %endif
2 <div class="pullrequests_section_head">${_('Opened by me')}</div>
6 <div class="pullrequests_section_head">${_('Opened by me')}</div>
3 <ul>
7 <ul>
4 %if c.my_pull_requests:
8 %if c.my_pull_requests:
@@ -2,14 +2,14 b''
2 <%inherit file="/base/base.html"/>
2 <%inherit file="/base/base.html"/>
3
3
4 <%def name="title()">
4 <%def name="title()">
5 ${_('Add users group')} - ${c.rhodecode_name}
5 ${_('Add user group')} - ${c.rhodecode_name}
6 </%def>
6 </%def>
7 <%def name="breadcrumbs_links()">
7 <%def name="breadcrumbs_links()">
8 ${h.link_to(_('Admin'),h.url('admin_home'))}
8 ${h.link_to(_('Admin'),h.url('admin_home'))}
9 &raquo;
9 &raquo;
10 ${h.link_to(_('Users groups'),h.url('users_groups'))}
10 ${h.link_to(_('User groups'),h.url('users_groups'))}
11 &raquo;
11 &raquo;
12 ${_('add new users group')}
12 ${_('add new user group')}
13 </%def>
13 </%def>
14
14
15 <%def name="page_nav()">
15 <%def name="page_nav()">
@@ -2,13 +2,13 b''
2 <%inherit file="/base/base.html"/>
2 <%inherit file="/base/base.html"/>
3
3
4 <%def name="title()">
4 <%def name="title()">
5 ${_('Edit users group')} ${c.users_group.users_group_name} - ${c.rhodecode_name}
5 ${_('Edit user group')} ${c.users_group.users_group_name} - ${c.rhodecode_name}
6 </%def>
6 </%def>
7
7
8 <%def name="breadcrumbs_links()">
8 <%def name="breadcrumbs_links()">
9 ${h.link_to(_('Admin'),h.url('admin_home'))}
9 ${h.link_to(_('Admin'),h.url('admin_home'))}
10 &raquo;
10 &raquo;
11 ${h.link_to(_('UsersGroups'),h.url('users_groups'))}
11 ${h.link_to(_('UserGroups'),h.url('users_groups'))}
12 &raquo;
12 &raquo;
13 ${_('edit')} "${c.users_group.users_group_name}"
13 ${_('edit')} "${c.users_group.users_group_name}"
14 </%def>
14 </%def>
@@ -2,13 +2,13 b''
2 <%inherit file="/base/base.html"/>
2 <%inherit file="/base/base.html"/>
3
3
4 <%def name="title()">
4 <%def name="title()">
5 ${_('Users groups administration')} - ${c.rhodecode_name}
5 ${_('User groups administration')} - ${c.rhodecode_name}
6 </%def>
6 </%def>
7
7
8 <%def name="breadcrumbs_links()">
8 <%def name="breadcrumbs_links()">
9 ${h.link_to(_('Admin'),h.url('admin_home'))}
9 ${h.link_to(_('Admin'),h.url('admin_home'))}
10 &raquo;
10 &raquo;
11 ${_('users groups')}
11 ${_('user groups')}
12 </%def>
12 </%def>
13
13
14 <%def name="page_nav()">
14 <%def name="page_nav()">
@@ -44,7 +44,7 b''
44 <td>
44 <td>
45 ${h.form(url('users_group', id=u_group.users_group_id),method='delete')}
45 ${h.form(url('users_group', id=u_group.users_group_id),method='delete')}
46 ${h.submit('remove_',_('delete'),id="remove_group_%s" % u_group.users_group_id,
46 ${h.submit('remove_',_('delete'),id="remove_group_%s" % u_group.users_group_id,
47 class_="delete_icon action_button",onclick="return confirm('"+_('Confirm to delete this users group: %s') % u_group.users_group_name+"');")}
47 class_="delete_icon action_button",onclick="return confirm('"+_('Confirm to delete this user group: %s') % u_group.users_group_name+"');")}
48 ${h.end_form()}
48 ${h.end_form()}
49 </td>
49 </td>
50 </tr>
50 </tr>
@@ -71,9 +71,9 b''
71 <ul class="admin_menu">
71 <ul class="admin_menu">
72 <li>${h.link_to(_('admin journal'),h.url('admin_home'),class_='journal')}</li>
72 <li>${h.link_to(_('admin journal'),h.url('admin_home'),class_='journal')}</li>
73 <li>${h.link_to(_('repositories'),h.url('repos'),class_='repos')}</li>
73 <li>${h.link_to(_('repositories'),h.url('repos'),class_='repos')}</li>
74 <li>${h.link_to(_('repositories groups'),h.url('repos_groups'),class_='repos_groups')}</li>
74 <li>${h.link_to(_('repository groups'),h.url('repos_groups'),class_='repos_groups')}</li>
75 <li>${h.link_to(_('users'),h.url('users'),class_='users')}</li>
75 <li>${h.link_to(_('users'),h.url('users'),class_='users')}</li>
76 <li>${h.link_to(_('users groups'),h.url('users_groups'),class_='groups')}</li>
76 <li>${h.link_to(_('user groups'),h.url('users_groups'),class_='groups')}</li>
77 <li>${h.link_to(_('permissions'),h.url('edit_permission',id='default'),class_='permissions')}</li>
77 <li>${h.link_to(_('permissions'),h.url('edit_permission',id='default'),class_='permissions')}</li>
78 <li>${h.link_to(_('ldap'),h.url('ldap_home'),class_='ldap')}</li>
78 <li>${h.link_to(_('ldap'),h.url('ldap_home'),class_='ldap')}</li>
79 <li>${h.link_to(_('defaults'),h.url('defaults'),class_='defaults')}</li>
79 <li>${h.link_to(_('defaults'),h.url('defaults'),class_='defaults')}</li>
@@ -233,7 +233,7 b''
233 <label for="username">${_('Username')}:</label>
233 <label for="username">${_('Username')}:</label>
234 </div>
234 </div>
235 <div class="input">
235 <div class="input">
236 ${h.text('username',class_='focus',size=40)}
236 ${h.text('username',class_='focus')}
237 </div>
237 </div>
238
238
239 </div>
239 </div>
@@ -242,7 +242,7 b''
242 <label for="password">${_('Password')}:</label>
242 <label for="password">${_('Password')}:</label>
243 </div>
243 </div>
244 <div class="input">
244 <div class="input">
245 ${h.password('password',class_='focus',size=40)}
245 ${h.password('password',class_='focus')}
246 </div>
246 </div>
247
247
248 </div>
248 </div>
@@ -52,7 +52,10 b''
52 'Open new pull request': "${_('Open new pull request')}",
52 'Open new pull request': "${_('Open new pull request')}",
53 'Open new pull request for selected changesets': "${_('Open new pull request for selected changesets')}",
53 'Open new pull request for selected changesets': "${_('Open new pull request for selected changesets')}",
54 'Show selected changes __S -> __E': "${_('Show selected changes __S -> __E')}",
54 'Show selected changes __S -> __E': "${_('Show selected changes __S -> __E')}",
55 'Show selected change __S': "${_('Show selected change __S')}",
55 'Selection link': "${_('Selection link')}",
56 'Selection link': "${_('Selection link')}",
57 'collapse diff': "${_('collapse diff')}",
58 'expand diff': "${_('expand diff')}",
56 };
59 };
57 var _TM = TRANSLATION_MAP;
60 var _TM = TRANSLATION_MAP;
58
61
@@ -27,7 +27,7 b''
27 </div>
27 </div>
28 <!-- end box / title -->
28 <!-- end box / title -->
29 %if c.repo_branches:
29 %if c.repo_branches:
30 <div class="info_box" id="compare_branches" style="clear: both;padding: 10px 19px;vertical-align: right;text-align: right;"><a href="#" class="ui-btn small">${_('Compare branches')}</a></div>
30 <div class="info_box" id="compare_branches" style="clear: both;padding: 10px 19px;text-align: right;"><a href="#" class="ui-btn small">${_('Compare branches')}</a></div>
31 %endif
31 %endif
32 <div class="table">
32 <div class="table">
33 <%include file='branches_data.html'/>
33 <%include file='branches_data.html'/>
@@ -33,15 +33,15 b''
33 <canvas id="graph_canvas"></canvas>
33 <canvas id="graph_canvas"></canvas>
34 </div>
34 </div>
35 <div id="graph_content">
35 <div id="graph_content">
36 <div class="info_box" style="clear: both;padding: 10px 6px;vertical-align: right;text-align: right;">
36 <div class="info_box" style="clear: both;padding: 10px 6px;text-align: right;">
37 <a href="#" class="ui-btn small" id="rev_range_container" style="display:none"></a>
37 <a href="#" class="ui-btn small" id="rev_range_container" style="display:none"></a>
38 <a href="#" class="ui-btn small" id="rev_range_clear" style="display:none">${_('Clear selection')}</a>
38 <a href="#" class="ui-btn small" id="rev_range_clear" style="display:none">${_('Clear selection')}</a>
39
39
40 %if c.rhodecode_db_repo.fork:
40 %if c.rhodecode_db_repo.fork:
41 <a title="${_('compare fork with %s' % c.rhodecode_db_repo.fork.repo_name)}" href="${h.url('compare_url',repo_name=c.rhodecode_db_repo.fork.repo_name,org_ref_type='branch',org_ref='default',other_repo=c.repo_name,other_ref_type='branch',other_ref=request.GET.get('branch') or 'default')}" class="ui-btn small">${_('Compare fork with parent')}</a>
41 <a title="${_('Compare fork with %s' % c.rhodecode_db_repo.fork.repo_name)}" href="${h.url('compare_url',repo_name=c.rhodecode_db_repo.fork.repo_name,org_ref_type='branch',org_ref='default',other_repo=c.repo_name,other_ref_type='branch',other_ref=request.GET.get('branch') or 'default')}" class="ui-btn small">${_('Compare fork with parent')}</a>
42 %endif
42 %endif
43 %if h.is_hg(c.rhodecode_repo):
43 %if h.is_hg(c.rhodecode_repo):
44 <a id="open_new_pr" href="${h.url('pullrequest_home',repo_name=c.repo_name)}" class="ui-btn small">${_('open new pull request')}</a>
44 <a id="open_new_pr" href="${h.url('pullrequest_form',repo_name=c.repo_name)}" class="ui-btn small">${_('Open new pull request')}</a>
45 %endif
45 %endif
46 </div>
46 </div>
47 <div class="container_header">
47 <div class="container_header">
@@ -72,7 +72,7 b''
72 </div>
72 </div>
73 <div class="mid">
73 <div class="mid">
74 <div class="message">${h.urlify_commit(cs.message, c.repo_name,h.url('changeset_home',repo_name=c.repo_name,revision=cs.raw_id))}</div>
74 <div class="message">${h.urlify_commit(cs.message, c.repo_name,h.url('changeset_home',repo_name=c.repo_name,revision=cs.raw_id))}</div>
75 <div class="expand"><span class="expandtext">&darr; ${_('show more')} &darr;</span></div>
75 <div class="expand"><span class="expandtext">&darr; ${_('Show more')} &darr;</span></div>
76 </div>
76 </div>
77 <div class="right">
77 <div class="right">
78 <div class="changes">
78 <div class="changes">
@@ -163,7 +163,6 b''
163 if(checked_checkboxes.length>0){
163 if(checked_checkboxes.length>0){
164 // modify open pull request to show we have selected cs
164 // modify open pull request to show we have selected cs
165 YUD.get('open_new_pr').innerHTML = _TM['Open new pull request for selected changesets'];
165 YUD.get('open_new_pr').innerHTML = _TM['Open new pull request for selected changesets'];
166
167 }else{
166 }else{
168 YUD.get('open_new_pr').innerHTML = _TM['Open new pull request'];
167 YUD.get('open_new_pr').innerHTML = _TM['Open new pull request'];
169 }
168 }
@@ -172,32 +171,13 b''
172 if(checked_checkboxes.length>0){
171 if(checked_checkboxes.length>0){
173 var rev_end = checked_checkboxes[0].name;
172 var rev_end = checked_checkboxes[0].name;
174 var rev_start = checked_checkboxes[checked_checkboxes.length-1].name;
173 var rev_start = checked_checkboxes[checked_checkboxes.length-1].name;
175
176 // now select all checkboxes in the middle.
177 var checked = false;
178 for (var i=0; i<checkboxes.length; i++){
179 var cb = checkboxes[i];
180 var rev = cb.name;
181
182 if (rev == rev_end){
183 checked = true;
184 }
185 if (checked){
186 cb.checked = true;
187 }
188 else{
189 cb.checked = false;
190 }
191 if (rev == rev_start){
192 checked = false;
193 }
194
195 }
196
197 var url = url_tmpl.replace('__REVRANGE__',
174 var url = url_tmpl.replace('__REVRANGE__',
198 rev_start+'...'+rev_end);
175 rev_start+'...'+rev_end);
199
176
200 var link = _TM['Show selected changes __S -> __E'];
177 var link = (rev_start == rev_end)
178 ? _TM['Show selected change __S']
179 : _TM['Show selected changes __S -> __E'];
180
201 link = link.replace('__S',rev_start.substr(0,6));
181 link = link.replace('__S',rev_start.substr(0,6));
202 link = link.replace('__E',rev_end.substr(0,6));
182 link = link.replace('__E',rev_end.substr(0,6));
203 YUD.get('rev_range_container').href = url;
183 YUD.get('rev_range_container').href = url;
@@ -4,7 +4,10 b''
4 ## ${diff_block.diff_block(change)}
4 ## ${diff_block.diff_block(change)}
5 ##
5 ##
6 <%def name="diff_block(change)">
6 <%def name="diff_block(change)">
7
7 <div class="diff-collapse">
8 <span target="${'diff-container-%s' % (id(change))}" class="diff-collapse-button">&uarr; ${_('collapse diff')} &uarr;</span>
9 </div>
10 <div class="diff-container" id="${'diff-container-%s' % (id(change))}">
8 %for FID,(cs1, cs2, change, path, diff, stats) in change.iteritems():
11 %for FID,(cs1, cs2, change, path, diff, stats) in change.iteritems():
9 ##%if op !='removed':
12 ##%if op !='removed':
10 <div id="${FID}_target" style="clear:both;margin-top:25px"></div>
13 <div id="${FID}_target" style="clear:both;margin-top:25px"></div>
@@ -37,7 +40,7 b''
37 </div>
40 </div>
38 ##%endif
41 ##%endif
39 %endfor
42 %endfor
40
43 </div>
41 </%def>
44 </%def>
42
45
43 <%def name="diff_block_simple(change)">
46 <%def name="diff_block_simple(change)">
@@ -49,8 +52,8 b''
49 <div class="changeset_header">
52 <div class="changeset_header">
50 <div class="changeset_file">
53 <div class="changeset_file">
51 ${h.safe_unicode(filenode_path)} |
54 ${h.safe_unicode(filenode_path)} |
52 <a class="spantag" href="${h.url('files_home', repo_name=c.repo_name, f_path=filenode_path, revision=c.org_ref)}">${c.org_ref_type}@${c.org_ref}</a> -&gt;
55 <a class="spantag" href="${h.url('files_home', repo_name=c.repo_name, f_path=filenode_path, revision=c.org_ref)}" title="${_('show file at latest version in this repo')}">${c.org_ref_type}@${h.short_id(c.org_ref) if c.org_ref_type=='rev' else c.org_ref}</a> -&gt;
53 <a class="spantag" href="${h.url('files_home', repo_name=c.repo_name, f_path=filenode_path, revision=c.other_ref)}">${c.other_ref_type}@${c.other_ref}</a>
56 <a class="spantag" href="${h.url('files_home', repo_name=c.repo_name, f_path=filenode_path, revision=c.other_ref)}" title="${_('show file at initial version in this repo')}">${c.other_ref_type}@${h.short_id(c.other_ref) if c.other_ref_type=='rev' else c.other_ref}</a>
54 </div>
57 </div>
55 </div>
58 </div>
56 </div>
59 </div>
@@ -1,12 +1,17 b''
1 ## -*- coding: utf-8 -*-
1 ## -*- coding: utf-8 -*-
2 <%inherit file="main.html"/>
2 <%inherit file="main.html"/>
3
3 ##message from user goes here
4 <h4>${subject}</h4>
4 <p>
5
5 ${cs_comment_user}: <br/>
6 ${body}
6 ${body}
7 </p>
8 %if status_change:
9 <span>${_('New status')} -&gt; ${status_change}</span>
10 %endif
11 <div>${_('View this comment here')}: ${cs_comment_url}</div>
7
12
8 % if status_change is not None:
13 <pre>
9 <div>
14 ${_('Repo')}: ${cs_target_repo}
10 ${_('New status')} -&gt; ${status_change}
15 ${_('Changeset')}: ${h.short_id(raw_id)}
11 </div>
16 ${_('desc')}: ${h.shorter(message, 256)}
12 % endif
17 </pre>
@@ -1,12 +1,11 b''
1 ## -*- coding: utf-8 -*-
1 ## -*- coding: utf-8 -*-
2 <%inherit file="main.html"/>
2 <%inherit file="main.html"/>
3
3
4 ${_('Hello')} ${user}
4 <h4>${_('Hello %s') % user}</h4>
5
5 <div>${_('We received a request to create a new password for your account.')}</div>
6 ${_('We received a request to create a new password for your account.')}
6 <div>${_('You can generate it by clicking following URL')}:</div>
7
7 <pre>
8 ${_('You can generate it by clicking following URL')}:
9
10 ${reset_url}
8 ${reset_url}
11
9 </pre>
12 ${_("If you didn't request new password please ignore this email.")}
10 <br/>
11 ${_("If you did not request new password please ignore this email.")}
@@ -10,8 +10,10 b''
10 </p>
10 </p>
11
11
12 <div>${_('revisions for reviewing')}</div>
12 <div>${_('revisions for reviewing')}</div>
13 <ul>
13 <pre>
14 %for r in pr_revisions:
14 %for r,r_msg in pr_revisions:
15 <li>${r}</li>
15 ${h.short_id(r)}:
16 ${h.shorter(r_msg, 256)}
17
16 %endfor
18 %endfor
17 </ul>
19 </pre>
@@ -1,13 +1,18 b''
1 ## -*- coding: utf-8 -*-
1 ## -*- coding: utf-8 -*-
2 <%inherit file="main.html"/>
2 <%inherit file="main.html"/>
3
3 ${_('Pull request #%s for repository %s') % (pr_id, pr_target_repo) |n}
4 ${_('User %s commented on pull request #%s for repository %s') % ('<b>%s</b>' % pr_comment_user, pr_id, pr_target_repo) |n}
4 ##message from user goes here
5 <p>
6 ${pr_comment_user}: <br/>
7 ${body}
8 </p>
5 <div>${_('View this comment here')}: ${pr_comment_url}</div>
9 <div>${_('View this comment here')}: ${pr_comment_url}</div>
6
10
7 <p>
8 ${body}
9
10 %if status_change:
11 %if status_change:
11 <span>${_('New status')} -&gt; ${status_change}</span>
12 %if closing_pr:
13 <span>${_('Closing pull request with status')} -&gt; ${status_change}</span>
14 %else:
15 <span>${_('New status')} -&gt; ${status_change}</span>
16 %endif
12 %endif
17 %endif
13 </p>
18 </p>
@@ -86,8 +86,11 b' YUE.onDOMReady(function(){'
86 h_lines.push(parseInt(highlight_ranges[pos]));
86 h_lines.push(parseInt(highlight_ranges[pos]));
87 }
87 }
88 }
88 }
89 highlight_lines(h_lines);
89 highlight_lines(h_lines);
90
90 var _first_line= YUD.get('L'+h_lines[0]);
91 if(_first_line){
92 _first_line.scrollIntoView()
93 }
91 }
94 }
92
95
93 // select code link event
96 // select code link event
@@ -48,7 +48,7 b''
48 <tr>
48 <tr>
49 <td>
49 <td>
50 <div style="white-space: nowrap">
50 <div style="white-space: nowrap">
51 <img class="icon" alt="${_('Repositories group')}" src="${h.url('/images/icons/database_link.png')}"/>
51 <img class="icon" alt="${_('Repository group')}" src="${h.url('/images/icons/database_link.png')}"/>
52 ${h.link_to(gr.name,url('repos_group_home',group_name=gr.group_name))}
52 ${h.link_to(gr.name,url('repos_group_home',group_name=gr.group_name))}
53 </div>
53 </div>
54 </td>
54 </td>
@@ -31,7 +31,7 b''
31 <label for="username">${_('Username')}:</label>
31 <label for="username">${_('Username')}:</label>
32 </div>
32 </div>
33 <div class="input">
33 <div class="input">
34 ${h.text('username',class_='focus',size=40)}
34 ${h.text('username',class_='focus large')}
35 </div>
35 </div>
36
36
37 </div>
37 </div>
@@ -40,7 +40,7 b''
40 <label for="password">${_('Password')}:</label>
40 <label for="password">${_('Password')}:</label>
41 </div>
41 </div>
42 <div class="input">
42 <div class="input">
43 ${h.password('password',class_='focus',size=40)}
43 ${h.password('password',class_='focus large')}
44 </div>
44 </div>
45
45
46 </div>
46 </div>
@@ -30,7 +30,7 b''
30 <span style="font-size: 20px">
30 <span style="font-size: 20px">
31 ${h.select('org_repo','',c.org_repos,class_='refs')}:${h.select('org_ref',c.default_org_ref,c.org_refs,class_='refs')}
31 ${h.select('org_repo','',c.org_repos,class_='refs')}:${h.select('org_ref',c.default_org_ref,c.org_refs,class_='refs')}
32 </span>
32 </span>
33 <div style="padding:5px 3px 3px 42px;">${c.rhodecode_db_repo.description}</div>
33 <div style="padding:5px 3px 3px 20px;">${c.rhodecode_db_repo.description}</div>
34 </div>
34 </div>
35 <div style="clear:both;padding-top: 10px"></div>
35 <div style="clear:both;padding-top: 10px"></div>
36 </div>
36 </div>
@@ -44,7 +44,7 b''
44 <span style="font-size: 20px">
44 <span style="font-size: 20px">
45 ${h.select('other_repo',c.default_other_repo,c.other_repos,class_='refs')}:${h.select('other_ref',c.default_other_ref,c.default_other_refs,class_='refs')}
45 ${h.select('other_repo',c.default_other_repo,c.other_repos,class_='refs')}:${h.select('other_ref',c.default_other_ref,c.default_other_refs,class_='refs')}
46 </span>
46 </span>
47 <div id="other_repo_desc" style="padding:5px 3px 3px 42px;"></div>
47 <div id="other_repo_desc" style="padding:5px 3px 3px 20px;"></div>
48 </div>
48 </div>
49 <div style="clear:both;padding-top: 10px"></div>
49 <div style="clear:both;padding-top: 10px"></div>
50 </div>
50 </div>
@@ -146,24 +146,25 b''
146
146
147 var select_refs = YUQ('#pull_request_form select.refs')
147 var select_refs = YUQ('#pull_request_form select.refs')
148 var rev_data = {
148 var rev_data = {
149 'org_repo': org_repo,
149 'org_repo': org_repo,
150 'org_ref': org_ref[1],
150 'org_ref': org_ref[2],
151 'org_ref_type': org_ref[0],
151 'org_ref_type': 'rev',
152 'other_repo': other_repo,
152 'other_repo': other_repo,
153 'other_ref': other_ref[1],
153 'other_ref': other_ref[2],
154 'other_ref_type': other_ref[0],
154 'other_ref_type': 'rev',
155 }; // gather the org/other ref and repo here
155 }; // gather the org/other ref and repo here
156
156
157 for (k in rev_data){
157 for (k in rev_data){
158 url = url.replace('__'+k+'__',rev_data[k]);
158 url = url.replace('__'+k+'__',rev_data[k]);
159 }
159 }
160
160
161 YUD.get('pull_request_overview').innerHTML = "${_('Loading ...')}";
162 YUD.get('pull_request_overview_url').href = url; // shouldn't have as_form ... but ...
163 YUD.setStyle(YUD.get('pull_request_overview_url').parentElement,'display','');
161 ypjax(url,'pull_request_overview', function(data){
164 ypjax(url,'pull_request_overview', function(data){
162 var sel_box = YUQ('#pull_request_form #other_repo')[0];
165 var sel_box = YUQ('#pull_request_form #other_repo')[0];
163 var repo_name = sel_box.options[sel_box.selectedIndex].value;
166 var repo_name = sel_box.options[sel_box.selectedIndex].value;
164 var _data = other_repos_info[repo_name];
167 var _data = other_repos_info[repo_name];
165 YUD.get('pull_request_overview_url').href = url;
166 YUD.setStyle(YUD.get('pull_request_overview_url').parentElement,'display','');
167 YUD.get('other_repo_desc').innerHTML = other_repos_info[repo_name]['description'];
168 YUD.get('other_repo_desc').innerHTML = other_repos_info[repo_name]['description'];
168 YUD.get('other_ref').innerHTML = other_repos_info[repo_name]['revs'];
169 YUD.get('other_ref').innerHTML = other_repos_info[repo_name]['revs'];
169 // select back the revision that was just compared
170 // select back the revision that was just compared
@@ -171,8 +172,8 b''
171 // reset && add the reviewer based on selected repo
172 // reset && add the reviewer based on selected repo
172 YUD.get('review_members').innerHTML = '';
173 YUD.get('review_members').innerHTML = '';
173 addReviewMember(_data.user.user_id, _data.user.firstname,
174 addReviewMember(_data.user.user_id, _data.user.firstname,
174 _data.user.lastname, _data.user.username,
175 _data.user.lastname, _data.user.username,
175 _data.user.gravatar_link);
176 _data.user.gravatar_link);
176 })
177 })
177 }
178 }
178
179
@@ -7,7 +7,7 b''
7 <%def name="breadcrumbs_links()">
7 <%def name="breadcrumbs_links()">
8 ${h.link_to(_(u'Home'),h.url('/'))}
8 ${h.link_to(_(u'Home'),h.url('/'))}
9 &raquo;
9 &raquo;
10 ${h.link_to(c.repo_name,h.url('changelog_home',repo_name=c.repo_name))}
10 ${h.repo_link(c.rhodecode_db_repo.groups_and_repo)}
11 &raquo;
11 &raquo;
12 ${_('Pull request #%s') % c.pull_request.pull_request_id}
12 ${_('Pull request #%s') % c.pull_request.pull_request_id}
13 </%def>
13 </%def>
@@ -22,7 +22,12 b''
22 %if c.pull_request.is_closed():
22 %if c.pull_request.is_closed():
23 <div style="padding:10px; font-size:22px;width:100%;text-align: center; color:#88D882">${_('Closed %s') % (h.age(c.pull_request.updated_on))} ${_('with status %s') % h.changeset_status_lbl(c.current_changeset_status)}</div>
23 <div style="padding:10px; font-size:22px;width:100%;text-align: center; color:#88D882">${_('Closed %s') % (h.age(c.pull_request.updated_on))} ${_('with status %s') % h.changeset_status_lbl(c.current_changeset_status)}</div>
24 %endif
24 %endif
25 <h3>${_('Title')}: ${c.pull_request.title}</h3>
25 <h3>
26 %if c.pull_request.is_closed():
27 <img src="${h.url('/images/icons/lock_go.png')}" title="${_('Closed')}"/>
28 %endif
29 <img src="${h.url('/images/icons/flag_status_%s.png' % str(c.pull_request.last_review_status))}" />
30 ${_('Title')}: ${c.pull_request.title}</h3>
26
31
27 <div class="form">
32 <div class="form">
28 <div id="summary" class="fields">
33 <div id="summary" class="fields">
@@ -4,7 +4,7 b''
4 <ul>
4 <ul>
5 %if c.rhodecode_repo.branches.values():
5 %if c.rhodecode_repo.branches.values():
6 %for cnt,branch in enumerate(c.rhodecode_repo.branches.items()):
6 %for cnt,branch in enumerate(c.rhodecode_repo.branches.items()):
7 <li><div><pre>${h.link_to('%s - %s' % (branch[0],h.short_id(branch[1])),h.url('files_home',repo_name=c.repo_name,revision=branch[0]))}</pre></div></li>
7 <li><div><pre>${h.link_to('%s - %s' % (branch[0],h.short_id(branch[1])),h.url('files_home',repo_name=c.repo_name,revision=(branch[0] if '/' not in branch[0] else branch[1]), at=branch[0]))}</pre></div></li>
8 %endfor
8 %endfor
9 %else:
9 %else:
10 <li>${h.link_to(_('There are no branches yet'),'#')}</li>
10 <li>${h.link_to(_('There are no branches yet'),'#')}</li>
@@ -16,7 +16,7 b''
16 <ul>
16 <ul>
17 %if c.rhodecode_repo.tags.values():
17 %if c.rhodecode_repo.tags.values():
18 %for cnt,tag in enumerate(c.rhodecode_repo.tags.items()):
18 %for cnt,tag in enumerate(c.rhodecode_repo.tags.items()):
19 <li><div><pre>${h.link_to('%s - %s' % (tag[0],h.short_id(tag[1])),h.url('files_home',repo_name=c.repo_name,revision=tag[0]))}</pre></div></li>
19 <li><div><pre>${h.link_to('%s - %s' % (tag[0],h.short_id(tag[1])),h.url('files_home',repo_name=c.repo_name,revision=(tag[0] if '/' not in tag[0] else tag[1]), at=tag[0]))}</pre></div></li>
20 %endfor
20 %endfor
21 %else:
21 %else:
22 <li>${h.link_to(_('There are no tags yet'),'#')}</li>
22 <li>${h.link_to(_('There are no tags yet'),'#')}</li>
@@ -29,7 +29,7 b''
29 <ul>
29 <ul>
30 %if c.rhodecode_repo.bookmarks.values():
30 %if c.rhodecode_repo.bookmarks.values():
31 %for cnt,book in enumerate(c.rhodecode_repo.bookmarks.items()):
31 %for cnt,book in enumerate(c.rhodecode_repo.bookmarks.items()):
32 <li><div><pre>${h.link_to('%s - %s' % (book[0],h.short_id(book[1])),h.url('files_home',repo_name=c.repo_name,revision=book[1]))}</pre></div></li>
32 <li><div><pre>${h.link_to('%s - %s' % (book[0],h.short_id(book[1])),h.url('files_home',repo_name=c.repo_name,revision=(book[0] if '/' not in book[0] else book[1]), at=book[0]))}</pre></div></li>
33 %endfor
33 %endfor
34 %else:
34 %else:
35 <li>${h.link_to(_('There are no bookmarks yet'),'#')}</li>
35 <li>${h.link_to(_('There are no bookmarks yet'),'#')}</li>
@@ -27,7 +27,7 b''
27 </div>
27 </div>
28 <!-- end box / title -->
28 <!-- end box / title -->
29 %if c.repo_tags:
29 %if c.repo_tags:
30 <div class="info_box" id="compare_tags" style="clear: both;padding: 10px 19px;vertical-align: right;text-align: right;"><a href="#" class="ui-btn small">${_('Compare tags')}</a></div>
30 <div class="info_box" id="compare_tags" style="clear: both;padding: 10px 19px;text-align: right;"><a href="#" class="ui-btn small">${_('Compare tags')}</a></div>
31 %endif
31 %endif
32 <div class="table">
32 <div class="table">
33 <%include file='tags_data.html'/>
33 <%include file='tags_data.html'/>
@@ -6,7 +6,7 b' from rhodecode.tests import *'
6 from rhodecode.lib.compat import json
6 from rhodecode.lib.compat import json
7 from rhodecode.lib.auth import AuthUser
7 from rhodecode.lib.auth import AuthUser
8 from rhodecode.model.user import UserModel
8 from rhodecode.model.user import UserModel
9 from rhodecode.model.users_group import UsersGroupModel
9 from rhodecode.model.users_group import UserGroupModel
10 from rhodecode.model.repo import RepoModel
10 from rhodecode.model.repo import RepoModel
11 from rhodecode.model.meta import Session
11 from rhodecode.model.meta import Session
12 from rhodecode.model.scm import ScmModel
12 from rhodecode.model.scm import ScmModel
@@ -43,19 +43,19 b' def api_call(test_obj, params):'
43 return response
43 return response
44
44
45
45
46 TEST_USERS_GROUP = 'test_users_group'
46 TEST_USER_GROUP = 'test_users_group'
47
47
48
48
49 def make_users_group(name=TEST_USERS_GROUP):
49 def make_users_group(name=TEST_USER_GROUP):
50 gr = UsersGroupModel().create(name=name)
50 gr = UserGroupModel().create(name=name)
51 UsersGroupModel().add_user_to_group(users_group=gr,
51 UserGroupModel().add_user_to_group(users_group=gr,
52 user=TEST_USER_ADMIN_LOGIN)
52 user=TEST_USER_ADMIN_LOGIN)
53 Session().commit()
53 Session().commit()
54 return gr
54 return gr
55
55
56
56
57 def destroy_users_group(name=TEST_USERS_GROUP):
57 def destroy_users_group(name=TEST_USER_GROUP):
58 UsersGroupModel().delete(users_group=name, force=True)
58 UserGroupModel().delete(users_group=name, force=True)
59 Session().commit()
59 Session().commit()
60
60
61
61
@@ -999,10 +999,10 b' class BaseTestApi(object):'
999
999
1000 def test_api_get_users_group(self):
1000 def test_api_get_users_group(self):
1001 id_, params = _build_data(self.apikey, 'get_users_group',
1001 id_, params = _build_data(self.apikey, 'get_users_group',
1002 usersgroupid=TEST_USERS_GROUP)
1002 usersgroupid=TEST_USER_GROUP)
1003 response = api_call(self, params)
1003 response = api_call(self, params)
1004
1004
1005 users_group = UsersGroupModel().get_group(TEST_USERS_GROUP)
1005 users_group = UserGroupModel().get_group(TEST_USER_GROUP)
1006 members = []
1006 members = []
1007 for user in users_group.members:
1007 for user in users_group.members:
1008 user = user.user
1008 user = user.user
@@ -1021,13 +1021,13 b' class BaseTestApi(object):'
1021 response = api_call(self, params)
1021 response = api_call(self, params)
1022
1022
1023 expected = []
1023 expected = []
1024 for gr_name in [TEST_USERS_GROUP, 'test_users_group2']:
1024 for gr_name in [TEST_USER_GROUP, 'test_users_group2']:
1025 users_group = UsersGroupModel().get_group(gr_name)
1025 users_group = UserGroupModel().get_group(gr_name)
1026 ret = users_group.get_api_data()
1026 ret = users_group.get_api_data()
1027 expected.append(ret)
1027 expected.append(ret)
1028 self._compare_ok(id_, expected, given=response.body)
1028 self._compare_ok(id_, expected, given=response.body)
1029
1029
1030 UsersGroupModel().delete(users_group='test_users_group2')
1030 UserGroupModel().delete(users_group='test_users_group2')
1031 Session().commit()
1031 Session().commit()
1032
1032
1033 def test_api_create_users_group(self):
1033 def test_api_create_users_group(self):
@@ -1037,8 +1037,8 b' class BaseTestApi(object):'
1037 response = api_call(self, params)
1037 response = api_call(self, params)
1038
1038
1039 ret = {
1039 ret = {
1040 'msg': 'created new users group `%s`' % group_name,
1040 'msg': 'created new user group `%s`' % group_name,
1041 'users_group': jsonify(UsersGroupModel()\
1041 'users_group': jsonify(UserGroupModel()\
1042 .get_by_name(group_name)\
1042 .get_by_name(group_name)\
1043 .get_api_data())
1043 .get_api_data())
1044 }
1044 }
@@ -1049,13 +1049,13 b' class BaseTestApi(object):'
1049
1049
1050 def test_api_get_users_group_that_exist(self):
1050 def test_api_get_users_group_that_exist(self):
1051 id_, params = _build_data(self.apikey, 'create_users_group',
1051 id_, params = _build_data(self.apikey, 'create_users_group',
1052 group_name=TEST_USERS_GROUP)
1052 group_name=TEST_USER_GROUP)
1053 response = api_call(self, params)
1053 response = api_call(self, params)
1054
1054
1055 expected = "users group `%s` already exist" % TEST_USERS_GROUP
1055 expected = "user group `%s` already exist" % TEST_USER_GROUP
1056 self._compare_error(id_, expected, given=response.body)
1056 self._compare_error(id_, expected, given=response.body)
1057
1057
1058 @mock.patch.object(UsersGroupModel, 'create', crash)
1058 @mock.patch.object(UserGroupModel, 'create', crash)
1059 def test_api_get_users_group_exception_occurred(self):
1059 def test_api_get_users_group_exception_occurred(self):
1060 group_name = 'exception_happens'
1060 group_name = 'exception_happens'
1061 id_, params = _build_data(self.apikey, 'create_users_group',
1061 id_, params = _build_data(self.apikey, 'create_users_group',
@@ -1067,7 +1067,7 b' class BaseTestApi(object):'
1067
1067
1068 def test_api_add_user_to_users_group(self):
1068 def test_api_add_user_to_users_group(self):
1069 gr_name = 'test_group'
1069 gr_name = 'test_group'
1070 UsersGroupModel().create(gr_name)
1070 UserGroupModel().create(gr_name)
1071 Session().commit()
1071 Session().commit()
1072 id_, params = _build_data(self.apikey, 'add_user_to_users_group',
1072 id_, params = _build_data(self.apikey, 'add_user_to_users_group',
1073 usersgroupid=gr_name,
1073 usersgroupid=gr_name,
@@ -1075,13 +1075,13 b' class BaseTestApi(object):'
1075 response = api_call(self, params)
1075 response = api_call(self, params)
1076
1076
1077 expected = {
1077 expected = {
1078 'msg': 'added member `%s` to users group `%s`' % (
1078 'msg': 'added member `%s` to user group `%s`' % (
1079 TEST_USER_ADMIN_LOGIN, gr_name
1079 TEST_USER_ADMIN_LOGIN, gr_name
1080 ),
1080 ),
1081 'success': True}
1081 'success': True}
1082 self._compare_ok(id_, expected, given=response.body)
1082 self._compare_ok(id_, expected, given=response.body)
1083
1083
1084 UsersGroupModel().delete(users_group=gr_name)
1084 UserGroupModel().delete(users_group=gr_name)
1085 Session().commit()
1085 Session().commit()
1086
1086
1087 def test_api_add_user_to_users_group_that_doesnt_exist(self):
1087 def test_api_add_user_to_users_group_that_doesnt_exist(self):
@@ -1090,29 +1090,29 b' class BaseTestApi(object):'
1090 userid=TEST_USER_ADMIN_LOGIN)
1090 userid=TEST_USER_ADMIN_LOGIN)
1091 response = api_call(self, params)
1091 response = api_call(self, params)
1092
1092
1093 expected = 'users group `%s` does not exist' % 'false-group'
1093 expected = 'user group `%s` does not exist' % 'false-group'
1094 self._compare_error(id_, expected, given=response.body)
1094 self._compare_error(id_, expected, given=response.body)
1095
1095
1096 @mock.patch.object(UsersGroupModel, 'add_user_to_group', crash)
1096 @mock.patch.object(UserGroupModel, 'add_user_to_group', crash)
1097 def test_api_add_user_to_users_group_exception_occurred(self):
1097 def test_api_add_user_to_users_group_exception_occurred(self):
1098 gr_name = 'test_group'
1098 gr_name = 'test_group'
1099 UsersGroupModel().create(gr_name)
1099 UserGroupModel().create(gr_name)
1100 Session().commit()
1100 Session().commit()
1101 id_, params = _build_data(self.apikey, 'add_user_to_users_group',
1101 id_, params = _build_data(self.apikey, 'add_user_to_users_group',
1102 usersgroupid=gr_name,
1102 usersgroupid=gr_name,
1103 userid=TEST_USER_ADMIN_LOGIN)
1103 userid=TEST_USER_ADMIN_LOGIN)
1104 response = api_call(self, params)
1104 response = api_call(self, params)
1105
1105
1106 expected = 'failed to add member to users group `%s`' % gr_name
1106 expected = 'failed to add member to user group `%s`' % gr_name
1107 self._compare_error(id_, expected, given=response.body)
1107 self._compare_error(id_, expected, given=response.body)
1108
1108
1109 UsersGroupModel().delete(users_group=gr_name)
1109 UserGroupModel().delete(users_group=gr_name)
1110 Session().commit()
1110 Session().commit()
1111
1111
1112 def test_api_remove_user_from_users_group(self):
1112 def test_api_remove_user_from_users_group(self):
1113 gr_name = 'test_group_3'
1113 gr_name = 'test_group_3'
1114 gr = UsersGroupModel().create(gr_name)
1114 gr = UserGroupModel().create(gr_name)
1115 UsersGroupModel().add_user_to_group(gr, user=TEST_USER_ADMIN_LOGIN)
1115 UserGroupModel().add_user_to_group(gr, user=TEST_USER_ADMIN_LOGIN)
1116 Session().commit()
1116 Session().commit()
1117 id_, params = _build_data(self.apikey, 'remove_user_from_users_group',
1117 id_, params = _build_data(self.apikey, 'remove_user_from_users_group',
1118 usersgroupid=gr_name,
1118 usersgroupid=gr_name,
@@ -1120,30 +1120,30 b' class BaseTestApi(object):'
1120 response = api_call(self, params)
1120 response = api_call(self, params)
1121
1121
1122 expected = {
1122 expected = {
1123 'msg': 'removed member `%s` from users group `%s`' % (
1123 'msg': 'removed member `%s` from user group `%s`' % (
1124 TEST_USER_ADMIN_LOGIN, gr_name
1124 TEST_USER_ADMIN_LOGIN, gr_name
1125 ),
1125 ),
1126 'success': True}
1126 'success': True}
1127 self._compare_ok(id_, expected, given=response.body)
1127 self._compare_ok(id_, expected, given=response.body)
1128
1128
1129 UsersGroupModel().delete(users_group=gr_name)
1129 UserGroupModel().delete(users_group=gr_name)
1130 Session().commit()
1130 Session().commit()
1131
1131
1132 @mock.patch.object(UsersGroupModel, 'remove_user_from_group', crash)
1132 @mock.patch.object(UserGroupModel, 'remove_user_from_group', crash)
1133 def test_api_remove_user_from_users_group_exception_occurred(self):
1133 def test_api_remove_user_from_users_group_exception_occurred(self):
1134 gr_name = 'test_group_3'
1134 gr_name = 'test_group_3'
1135 gr = UsersGroupModel().create(gr_name)
1135 gr = UserGroupModel().create(gr_name)
1136 UsersGroupModel().add_user_to_group(gr, user=TEST_USER_ADMIN_LOGIN)
1136 UserGroupModel().add_user_to_group(gr, user=TEST_USER_ADMIN_LOGIN)
1137 Session().commit()
1137 Session().commit()
1138 id_, params = _build_data(self.apikey, 'remove_user_from_users_group',
1138 id_, params = _build_data(self.apikey, 'remove_user_from_users_group',
1139 usersgroupid=gr_name,
1139 usersgroupid=gr_name,
1140 userid=TEST_USER_ADMIN_LOGIN)
1140 userid=TEST_USER_ADMIN_LOGIN)
1141 response = api_call(self, params)
1141 response = api_call(self, params)
1142
1142
1143 expected = 'failed to remove member from users group `%s`' % gr_name
1143 expected = 'failed to remove member from user group `%s`' % gr_name
1144 self._compare_error(id_, expected, given=response.body)
1144 self._compare_error(id_, expected, given=response.body)
1145
1145
1146 UsersGroupModel().delete(users_group=gr_name)
1146 UserGroupModel().delete(users_group=gr_name)
1147 Session().commit()
1147 Session().commit()
1148
1148
1149 @parameterized.expand([('none', 'repository.none'),
1149 @parameterized.expand([('none', 'repository.none'),
@@ -1224,13 +1224,13 b' class BaseTestApi(object):'
1224 def test_api_grant_users_group_permission(self, name, perm):
1224 def test_api_grant_users_group_permission(self, name, perm):
1225 id_, params = _build_data(self.apikey, 'grant_users_group_permission',
1225 id_, params = _build_data(self.apikey, 'grant_users_group_permission',
1226 repoid=self.REPO,
1226 repoid=self.REPO,
1227 usersgroupid=TEST_USERS_GROUP,
1227 usersgroupid=TEST_USER_GROUP,
1228 perm=perm)
1228 perm=perm)
1229 response = api_call(self, params)
1229 response = api_call(self, params)
1230
1230
1231 ret = {
1231 ret = {
1232 'msg': 'Granted perm: `%s` for users group: `%s` in repo: `%s`' % (
1232 'msg': 'Granted perm: `%s` for user group: `%s` in repo: `%s`' % (
1233 perm, TEST_USERS_GROUP, self.REPO
1233 perm, TEST_USER_GROUP, self.REPO
1234 ),
1234 ),
1235 'success': True
1235 'success': True
1236 }
1236 }
@@ -1241,7 +1241,7 b' class BaseTestApi(object):'
1241 perm = 'haha.no.permission'
1241 perm = 'haha.no.permission'
1242 id_, params = _build_data(self.apikey, 'grant_users_group_permission',
1242 id_, params = _build_data(self.apikey, 'grant_users_group_permission',
1243 repoid=self.REPO,
1243 repoid=self.REPO,
1244 usersgroupid=TEST_USERS_GROUP,
1244 usersgroupid=TEST_USER_GROUP,
1245 perm=perm)
1245 perm=perm)
1246 response = api_call(self, params)
1246 response = api_call(self, params)
1247
1247
@@ -1253,28 +1253,28 b' class BaseTestApi(object):'
1253 perm = 'repository.read'
1253 perm = 'repository.read'
1254 id_, params = _build_data(self.apikey, 'grant_users_group_permission',
1254 id_, params = _build_data(self.apikey, 'grant_users_group_permission',
1255 repoid=self.REPO,
1255 repoid=self.REPO,
1256 usersgroupid=TEST_USERS_GROUP,
1256 usersgroupid=TEST_USER_GROUP,
1257 perm=perm)
1257 perm=perm)
1258 response = api_call(self, params)
1258 response = api_call(self, params)
1259
1259
1260 expected = 'failed to edit permission for users group: `%s` in repo: `%s`' % (
1260 expected = 'failed to edit permission for user group: `%s` in repo: `%s`' % (
1261 TEST_USERS_GROUP, self.REPO
1261 TEST_USER_GROUP, self.REPO
1262 )
1262 )
1263 self._compare_error(id_, expected, given=response.body)
1263 self._compare_error(id_, expected, given=response.body)
1264
1264
1265 def test_api_revoke_users_group_permission(self):
1265 def test_api_revoke_users_group_permission(self):
1266 RepoModel().grant_users_group_permission(repo=self.REPO,
1266 RepoModel().grant_users_group_permission(repo=self.REPO,
1267 group_name=TEST_USERS_GROUP,
1267 group_name=TEST_USER_GROUP,
1268 perm='repository.read')
1268 perm='repository.read')
1269 Session().commit()
1269 Session().commit()
1270 id_, params = _build_data(self.apikey, 'revoke_users_group_permission',
1270 id_, params = _build_data(self.apikey, 'revoke_users_group_permission',
1271 repoid=self.REPO,
1271 repoid=self.REPO,
1272 usersgroupid=TEST_USERS_GROUP,)
1272 usersgroupid=TEST_USER_GROUP,)
1273 response = api_call(self, params)
1273 response = api_call(self, params)
1274
1274
1275 expected = {
1275 expected = {
1276 'msg': 'Revoked perm for users group: `%s` in repo: `%s`' % (
1276 'msg': 'Revoked perm for user group: `%s` in repo: `%s`' % (
1277 TEST_USERS_GROUP, self.REPO
1277 TEST_USER_GROUP, self.REPO
1278 ),
1278 ),
1279 'success': True
1279 'success': True
1280 }
1280 }
@@ -1285,10 +1285,10 b' class BaseTestApi(object):'
1285
1285
1286 id_, params = _build_data(self.apikey, 'revoke_users_group_permission',
1286 id_, params = _build_data(self.apikey, 'revoke_users_group_permission',
1287 repoid=self.REPO,
1287 repoid=self.REPO,
1288 usersgroupid=TEST_USERS_GROUP,)
1288 usersgroupid=TEST_USER_GROUP,)
1289 response = api_call(self, params)
1289 response = api_call(self, params)
1290
1290
1291 expected = 'failed to edit permission for users group: `%s` in repo: `%s`' % (
1291 expected = 'failed to edit permission for user group: `%s` in repo: `%s`' % (
1292 TEST_USERS_GROUP, self.REPO
1292 TEST_USER_GROUP, self.REPO
1293 )
1293 )
1294 self._compare_error(id_, expected, given=response.body)
1294 self._compare_error(id_, expected, given=response.body)
@@ -1,7 +1,7 b''
1 from rhodecode.tests import *
1 from rhodecode.tests import *
2 from rhodecode.model.db import UsersGroup, UsersGroupToPerm, Permission
2 from rhodecode.model.db import UserGroup, UserGroupToPerm, Permission
3
3
4 TEST_USERS_GROUP = 'admins_test'
4 TEST_USER_GROUP = 'admins_test'
5
5
6
6
7 class TestAdminUsersGroupsController(TestController):
7 class TestAdminUsersGroupsController(TestController):
@@ -15,14 +15,14 b' class TestAdminUsersGroupsController(Tes'
15
15
16 def test_create(self):
16 def test_create(self):
17 self.log_user()
17 self.log_user()
18 users_group_name = TEST_USERS_GROUP
18 users_group_name = TEST_USER_GROUP
19 response = self.app.post(url('users_groups'),
19 response = self.app.post(url('users_groups'),
20 {'users_group_name': users_group_name,
20 {'users_group_name': users_group_name,
21 'active':True})
21 'active':True})
22 response.follow()
22 response.follow()
23
23
24 self.checkSessionFlash(response,
24 self.checkSessionFlash(response,
25 'created users group %s' % TEST_USERS_GROUP)
25 'created user group %s' % TEST_USER_GROUP)
26
26
27 def test_new(self):
27 def test_new(self):
28 response = self.app.get(url('new_users_group'))
28 response = self.app.get(url('new_users_group'))
@@ -39,50 +39,50 b' class TestAdminUsersGroupsController(Tes'
39
39
40 def test_delete(self):
40 def test_delete(self):
41 self.log_user()
41 self.log_user()
42 users_group_name = TEST_USERS_GROUP + 'another'
42 users_group_name = TEST_USER_GROUP + 'another'
43 response = self.app.post(url('users_groups'),
43 response = self.app.post(url('users_groups'),
44 {'users_group_name':users_group_name,
44 {'users_group_name':users_group_name,
45 'active':True})
45 'active':True})
46 response.follow()
46 response.follow()
47
47
48 self.checkSessionFlash(response,
48 self.checkSessionFlash(response,
49 'created users group %s' % users_group_name)
49 'created user group %s' % users_group_name)
50
50
51 gr = self.Session.query(UsersGroup)\
51 gr = self.Session.query(UserGroup)\
52 .filter(UsersGroup.users_group_name ==
52 .filter(UserGroup.users_group_name ==
53 users_group_name).one()
53 users_group_name).one()
54
54
55 response = self.app.delete(url('users_group', id=gr.users_group_id))
55 response = self.app.delete(url('users_group', id=gr.users_group_id))
56
56
57 gr = self.Session.query(UsersGroup)\
57 gr = self.Session.query(UserGroup)\
58 .filter(UsersGroup.users_group_name ==
58 .filter(UserGroup.users_group_name ==
59 users_group_name).scalar()
59 users_group_name).scalar()
60
60
61 self.assertEqual(gr, None)
61 self.assertEqual(gr, None)
62
62
63 def test_enable_repository_read_on_group(self):
63 def test_enable_repository_read_on_group(self):
64 self.log_user()
64 self.log_user()
65 users_group_name = TEST_USERS_GROUP + 'another2'
65 users_group_name = TEST_USER_GROUP + 'another2'
66 response = self.app.post(url('users_groups'),
66 response = self.app.post(url('users_groups'),
67 {'users_group_name': users_group_name,
67 {'users_group_name': users_group_name,
68 'active': True})
68 'active': True})
69 response.follow()
69 response.follow()
70
70
71 ug = UsersGroup.get_by_group_name(users_group_name)
71 ug = UserGroup.get_by_group_name(users_group_name)
72 self.checkSessionFlash(response,
72 self.checkSessionFlash(response,
73 'created users group %s' % users_group_name)
73 'created user group %s' % users_group_name)
74 ## ENABLE REPO CREATE ON A GROUP
74 ## ENABLE REPO CREATE ON A GROUP
75 response = self.app.put(url('users_group_perm', id=ug.users_group_id),
75 response = self.app.put(url('users_group_perm', id=ug.users_group_id),
76 {'create_repo_perm': True})
76 {'create_repo_perm': True})
77
77
78 response.follow()
78 response.follow()
79 ug = UsersGroup.get_by_group_name(users_group_name)
79 ug = UserGroup.get_by_group_name(users_group_name)
80 p = Permission.get_by_key('hg.create.repository')
80 p = Permission.get_by_key('hg.create.repository')
81 p2 = Permission.get_by_key('hg.fork.none')
81 p2 = Permission.get_by_key('hg.fork.none')
82 # check if user has this perms, they should be here since
82 # check if user has this perms, they should be here since
83 # defaults are on
83 # defaults are on
84 perms = UsersGroupToPerm.query()\
84 perms = UserGroupToPerm.query()\
85 .filter(UsersGroupToPerm.users_group == ug).all()
85 .filter(UserGroupToPerm.users_group == ug).all()
86
86
87 self.assertEqual(
87 self.assertEqual(
88 [[x.users_group_id, x.permission_id, ] for x in perms],
88 [[x.users_group_id, x.permission_id, ] for x in perms],
@@ -95,13 +95,13 b' class TestAdminUsersGroupsController(Tes'
95 {})
95 {})
96
96
97 response.follow()
97 response.follow()
98 ug = UsersGroup.get_by_group_name(users_group_name)
98 ug = UserGroup.get_by_group_name(users_group_name)
99 p = Permission.get_by_key('hg.create.none')
99 p = Permission.get_by_key('hg.create.none')
100 p2 = Permission.get_by_key('hg.fork.none')
100 p2 = Permission.get_by_key('hg.fork.none')
101 # check if user has this perms, they should be here since
101 # check if user has this perms, they should be here since
102 # defaults are on
102 # defaults are on
103 perms = UsersGroupToPerm.query()\
103 perms = UserGroupToPerm.query()\
104 .filter(UsersGroupToPerm.users_group == ug).all()
104 .filter(UserGroupToPerm.users_group == ug).all()
105
105
106 self.assertEqual(
106 self.assertEqual(
107 sorted([[x.users_group_id, x.permission_id, ] for x in perms]),
107 sorted([[x.users_group_id, x.permission_id, ] for x in perms]),
@@ -110,18 +110,18 b' class TestAdminUsersGroupsController(Tes'
110 )
110 )
111
111
112 # DELETE !
112 # DELETE !
113 ug = UsersGroup.get_by_group_name(users_group_name)
113 ug = UserGroup.get_by_group_name(users_group_name)
114 ugid = ug.users_group_id
114 ugid = ug.users_group_id
115 response = self.app.delete(url('users_group', id=ug.users_group_id))
115 response = self.app.delete(url('users_group', id=ug.users_group_id))
116 response = response.follow()
116 response = response.follow()
117 gr = self.Session.query(UsersGroup)\
117 gr = self.Session.query(UserGroup)\
118 .filter(UsersGroup.users_group_name ==
118 .filter(UserGroup.users_group_name ==
119 users_group_name).scalar()
119 users_group_name).scalar()
120
120
121 self.assertEqual(gr, None)
121 self.assertEqual(gr, None)
122 p = Permission.get_by_key('hg.create.repository')
122 p = Permission.get_by_key('hg.create.repository')
123 perms = UsersGroupToPerm.query()\
123 perms = UserGroupToPerm.query()\
124 .filter(UsersGroupToPerm.users_group_id == ugid).all()
124 .filter(UserGroupToPerm.users_group_id == ugid).all()
125 perms = [[x.users_group_id,
125 perms = [[x.users_group_id,
126 x.permission_id, ] for x in perms]
126 x.permission_id, ] for x in perms]
127 self.assertEqual(
127 self.assertEqual(
@@ -131,27 +131,27 b' class TestAdminUsersGroupsController(Tes'
131
131
132 def test_enable_repository_fork_on_group(self):
132 def test_enable_repository_fork_on_group(self):
133 self.log_user()
133 self.log_user()
134 users_group_name = TEST_USERS_GROUP + 'another2'
134 users_group_name = TEST_USER_GROUP + 'another2'
135 response = self.app.post(url('users_groups'),
135 response = self.app.post(url('users_groups'),
136 {'users_group_name': users_group_name,
136 {'users_group_name': users_group_name,
137 'active': True})
137 'active': True})
138 response.follow()
138 response.follow()
139
139
140 ug = UsersGroup.get_by_group_name(users_group_name)
140 ug = UserGroup.get_by_group_name(users_group_name)
141 self.checkSessionFlash(response,
141 self.checkSessionFlash(response,
142 'created users group %s' % users_group_name)
142 'created user group %s' % users_group_name)
143 ## ENABLE REPO CREATE ON A GROUP
143 ## ENABLE REPO CREATE ON A GROUP
144 response = self.app.put(url('users_group_perm', id=ug.users_group_id),
144 response = self.app.put(url('users_group_perm', id=ug.users_group_id),
145 {'fork_repo_perm': True})
145 {'fork_repo_perm': True})
146
146
147 response.follow()
147 response.follow()
148 ug = UsersGroup.get_by_group_name(users_group_name)
148 ug = UserGroup.get_by_group_name(users_group_name)
149 p = Permission.get_by_key('hg.create.none')
149 p = Permission.get_by_key('hg.create.none')
150 p2 = Permission.get_by_key('hg.fork.repository')
150 p2 = Permission.get_by_key('hg.fork.repository')
151 # check if user has this perms, they should be here since
151 # check if user has this perms, they should be here since
152 # defaults are on
152 # defaults are on
153 perms = UsersGroupToPerm.query()\
153 perms = UserGroupToPerm.query()\
154 .filter(UsersGroupToPerm.users_group == ug).all()
154 .filter(UserGroupToPerm.users_group == ug).all()
155
155
156 self.assertEqual(
156 self.assertEqual(
157 [[x.users_group_id, x.permission_id, ] for x in perms],
157 [[x.users_group_id, x.permission_id, ] for x in perms],
@@ -164,13 +164,13 b' class TestAdminUsersGroupsController(Tes'
164 {})
164 {})
165
165
166 response.follow()
166 response.follow()
167 ug = UsersGroup.get_by_group_name(users_group_name)
167 ug = UserGroup.get_by_group_name(users_group_name)
168 p = Permission.get_by_key('hg.create.none')
168 p = Permission.get_by_key('hg.create.none')
169 p2 = Permission.get_by_key('hg.fork.none')
169 p2 = Permission.get_by_key('hg.fork.none')
170 # check if user has this perms, they should be here since
170 # check if user has this perms, they should be here since
171 # defaults are on
171 # defaults are on
172 perms = UsersGroupToPerm.query()\
172 perms = UserGroupToPerm.query()\
173 .filter(UsersGroupToPerm.users_group == ug).all()
173 .filter(UserGroupToPerm.users_group == ug).all()
174
174
175 self.assertEqual(
175 self.assertEqual(
176 [[x.users_group_id, x.permission_id, ] for x in perms],
176 [[x.users_group_id, x.permission_id, ] for x in perms],
@@ -179,18 +179,18 b' class TestAdminUsersGroupsController(Tes'
179 )
179 )
180
180
181 # DELETE !
181 # DELETE !
182 ug = UsersGroup.get_by_group_name(users_group_name)
182 ug = UserGroup.get_by_group_name(users_group_name)
183 ugid = ug.users_group_id
183 ugid = ug.users_group_id
184 response = self.app.delete(url('users_group', id=ug.users_group_id))
184 response = self.app.delete(url('users_group', id=ug.users_group_id))
185 response = response.follow()
185 response = response.follow()
186 gr = self.Session.query(UsersGroup)\
186 gr = self.Session.query(UserGroup)\
187 .filter(UsersGroup.users_group_name ==
187 .filter(UserGroup.users_group_name ==
188 users_group_name).scalar()
188 users_group_name).scalar()
189
189
190 self.assertEqual(gr, None)
190 self.assertEqual(gr, None)
191 p = Permission.get_by_key('hg.fork.repository')
191 p = Permission.get_by_key('hg.fork.repository')
192 perms = UsersGroupToPerm.query()\
192 perms = UserGroupToPerm.query()\
193 .filter(UsersGroupToPerm.users_group_id == ugid).all()
193 .filter(UserGroupToPerm.users_group_id == ugid).all()
194 perms = [[x.users_group_id,
194 perms = [[x.users_group_id,
195 x.permission_id, ] for x in perms]
195 x.permission_id, ] for x in perms]
196 self.assertEqual(
196 self.assertEqual(
@@ -120,7 +120,7 b' class TestCompareController(TestControll'
120 ## files
120 ## files
121 response.mustcontain("""<a href="/%s/compare/branch@%s...branch@%s?other_repo=%s#C--826e8142e6ba">file1</a>""" % (repo1.repo_name, rev2, rev1, repo2.repo_name))
121 response.mustcontain("""<a href="/%s/compare/branch@%s...branch@%s?other_repo=%s#C--826e8142e6ba">file1</a>""" % (repo1.repo_name, rev2, rev1, repo2.repo_name))
122 #swap
122 #swap
123 response.mustcontain("""<a href="/%s/compare/branch@%s...branch@%s?as_form=None&amp;other_repo=%s">[swap]</a>""" % (repo2.repo_name, rev1, rev2, repo1.repo_name))
123 response.mustcontain("""<a href="/%s/compare/branch@%s...branch@%s?other_repo=%s">[swap]</a>""" % (repo2.repo_name, rev1, rev2, repo1.repo_name))
124
124
125 def test_compare_forks_on_branch_extra_commits_origin_has_incomming_hg(self):
125 def test_compare_forks_on_branch_extra_commits_origin_has_incomming_hg(self):
126 self.log_user()
126 self.log_user()
@@ -173,7 +173,7 b' class TestCompareController(TestControll'
173 ## files
173 ## files
174 response.mustcontain("""<a href="/%s/compare/branch@%s...branch@%s?other_repo=%s#C--826e8142e6ba">file1</a>""" % (repo1.repo_name, rev2, rev1, repo2.repo_name))
174 response.mustcontain("""<a href="/%s/compare/branch@%s...branch@%s?other_repo=%s#C--826e8142e6ba">file1</a>""" % (repo1.repo_name, rev2, rev1, repo2.repo_name))
175 #swap
175 #swap
176 response.mustcontain("""<a href="/%s/compare/branch@%s...branch@%s?as_form=None&amp;other_repo=%s">[swap]</a>""" % (repo2.repo_name, rev1, rev2, repo1.repo_name))
176 response.mustcontain("""<a href="/%s/compare/branch@%s...branch@%s?other_repo=%s">[swap]</a>""" % (repo2.repo_name, rev1, rev2, repo1.repo_name))
177
177
178 def test_compare_cherry_pick_changesets_from_bottom(self):
178 def test_compare_cherry_pick_changesets_from_bottom(self):
179
179
@@ -6,7 +6,7 b' class TestReposGroupsController(TestCont'
6 def test_index(self):
6 def test_index(self):
7 self.log_user()
7 self.log_user()
8 response = self.app.get(url('repos_groups'))
8 response = self.app.get(url('repos_groups'))
9 response.mustcontain('There are no repositories groups yet')
9 response.mustcontain('There are no repository groups yet')
10
10
11 # def test_index_as_xml(self):
11 # def test_index_as_xml(self):
12 # response = self.app.get(url('formatted_repos_groups', format='xml'))
12 # response = self.app.get(url('formatted_repos_groups', format='xml'))
@@ -4,11 +4,11 b' from rhodecode.tests import *'
4 from rhodecode.tests.models.common import _make_group
4 from rhodecode.tests.models.common import _make_group
5 from rhodecode.model.repos_group import ReposGroupModel
5 from rhodecode.model.repos_group import ReposGroupModel
6 from rhodecode.model.repo import RepoModel
6 from rhodecode.model.repo import RepoModel
7 from rhodecode.model.db import RepoGroup, User, UsersGroupRepoGroupToPerm
7 from rhodecode.model.db import RepoGroup, User, UserGroupRepoGroupToPerm
8 from rhodecode.model.user import UserModel
8 from rhodecode.model.user import UserModel
9
9
10 from rhodecode.model.meta import Session
10 from rhodecode.model.meta import Session
11 from rhodecode.model.users_group import UsersGroupModel
11 from rhodecode.model.users_group import UserGroupModel
12 from rhodecode.lib.auth import AuthUser
12 from rhodecode.lib.auth import AuthUser
13 from rhodecode.tests.api.api_base import create_repo
13 from rhodecode.tests.api.api_base import create_repo
14
14
@@ -51,7 +51,7 b' class TestPermissions(unittest.TestCase)'
51 ReposGroupModel().delete(self.g2.group_id)
51 ReposGroupModel().delete(self.g2.group_id)
52
52
53 if hasattr(self, 'ug1'):
53 if hasattr(self, 'ug1'):
54 UsersGroupModel().delete(self.ug1, force=True)
54 UserGroupModel().delete(self.ug1, force=True)
55
55
56 Session().commit()
56 Session().commit()
57
57
@@ -124,10 +124,10 b' class TestPermissions(unittest.TestCase)'
124
124
125 def test_propagated_permission_from_users_group_by_explicit_perms_exist(self):
125 def test_propagated_permission_from_users_group_by_explicit_perms_exist(self):
126 # make group
126 # make group
127 self.ug1 = UsersGroupModel().create('G1')
127 self.ug1 = UserGroupModel().create('G1')
128 # add user to group
128 # add user to group
129
129
130 UsersGroupModel().add_user_to_group(self.ug1, self.u1)
130 UserGroupModel().add_user_to_group(self.ug1, self.u1)
131
131
132 # set permission to lower
132 # set permission to lower
133 new_perm = 'repository.none'
133 new_perm = 'repository.none'
@@ -158,10 +158,10 b' class TestPermissions(unittest.TestCase)'
158
158
159 def test_propagated_permission_from_users_group(self):
159 def test_propagated_permission_from_users_group(self):
160 # make group
160 # make group
161 self.ug1 = UsersGroupModel().create('G1')
161 self.ug1 = UserGroupModel().create('G1')
162 # add user to group
162 # add user to group
163
163
164 UsersGroupModel().add_user_to_group(self.ug1, self.u3)
164 UserGroupModel().add_user_to_group(self.ug1, self.u3)
165
165
166 # grant perm for group this should override default permission from user
166 # grant perm for group this should override default permission from user
167 new_perm_gr = 'repository.write'
167 new_perm_gr = 'repository.write'
@@ -183,9 +183,9 b' class TestPermissions(unittest.TestCase)'
183
183
184 def test_propagated_permission_from_users_group_lower_weight(self):
184 def test_propagated_permission_from_users_group_lower_weight(self):
185 # make group
185 # make group
186 self.ug1 = UsersGroupModel().create('G1')
186 self.ug1 = UserGroupModel().create('G1')
187 # add user to group
187 # add user to group
188 UsersGroupModel().add_user_to_group(self.ug1, self.u1)
188 UserGroupModel().add_user_to_group(self.ug1, self.u1)
189
189
190 # set permission to lower
190 # set permission to lower
191 new_perm_h = 'repository.write'
191 new_perm_h = 'repository.write'
@@ -299,13 +299,13 b' class TestPermissions(unittest.TestCase)'
299 user=self.anon,
299 user=self.anon,
300 perm='group.none')
300 perm='group.none')
301 # make group
301 # make group
302 self.ug1 = UsersGroupModel().create('G1')
302 self.ug1 = UserGroupModel().create('G1')
303 # add user to group
303 # add user to group
304 UsersGroupModel().add_user_to_group(self.ug1, self.u1)
304 UserGroupModel().add_user_to_group(self.ug1, self.u1)
305 Session().commit()
305 Session().commit()
306
306
307 # check if user is in the group
307 # check if user is in the group
308 membrs = [x.user_id for x in UsersGroupModel().get(self.ug1.users_group_id).members]
308 membrs = [x.user_id for x in UserGroupModel().get(self.ug1.users_group_id).members]
309 self.assertEqual(membrs, [self.u1.user_id])
309 self.assertEqual(membrs, [self.u1.user_id])
310 # add some user to that group
310 # add some user to that group
311
311
@@ -324,9 +324,9 b' class TestPermissions(unittest.TestCase)'
324 perm='group.read')
324 perm='group.read')
325 Session().commit()
325 Session().commit()
326 # check if the
326 # check if the
327 obj = Session().query(UsersGroupRepoGroupToPerm)\
327 obj = Session().query(UserGroupRepoGroupToPerm)\
328 .filter(UsersGroupRepoGroupToPerm.group == self.g1)\
328 .filter(UserGroupRepoGroupToPerm.group == self.g1)\
329 .filter(UsersGroupRepoGroupToPerm.users_group == self.ug1)\
329 .filter(UserGroupRepoGroupToPerm.users_group == self.ug1)\
330 .scalar()
330 .scalar()
331 self.assertEqual(obj.permission.permission_name, 'group.read')
331 self.assertEqual(obj.permission.permission_name, 'group.read')
332
332
@@ -439,10 +439,10 b' class TestPermissions(unittest.TestCase)'
439 u1_auth = AuthUser(user_id=self.u1.user_id)
439 u1_auth = AuthUser(user_id=self.u1.user_id)
440 self.assertEqual(u1_auth.permissions['repositories']['myownrepo'],
440 self.assertEqual(u1_auth.permissions['repositories']['myownrepo'],
441 'repository.admin')
441 'repository.admin')
442 #set his permission as users group, he should still be admin
442 #set his permission as user group, he should still be admin
443 self.ug1 = UsersGroupModel().create('G1')
443 self.ug1 = UserGroupModel().create('G1')
444 # add user to group
444 # add user to group
445 UsersGroupModel().add_user_to_group(self.ug1, self.u1)
445 UserGroupModel().add_user_to_group(self.ug1, self.u1)
446 RepoModel().grant_users_group_permission(repo, group_name=self.ug1,
446 RepoModel().grant_users_group_permission(repo, group_name=self.ug1,
447 perm='repository.none')
447 perm='repository.none')
448
448
@@ -1,12 +1,12 b''
1 import unittest
1 import unittest
2 from rhodecode.tests import *
2 from rhodecode.tests import *
3
3
4 from rhodecode.model.db import User, UsersGroup, UsersGroupMember, UserEmailMap,\
4 from rhodecode.model.db import User, UserGroup, UserGroupMember, UserEmailMap,\
5 Permission
5 Permission
6 from rhodecode.model.user import UserModel
6 from rhodecode.model.user import UserModel
7
7
8 from rhodecode.model.meta import Session
8 from rhodecode.model.meta import Session
9 from rhodecode.model.users_group import UsersGroupModel
9 from rhodecode.model.users_group import UserGroupModel
10
10
11
11
12 class TestUser(unittest.TestCase):
12 class TestUser(unittest.TestCase):
@@ -22,19 +22,19 b' class TestUser(unittest.TestCase):'
22 Session().commit()
22 Session().commit()
23 self.assertEqual(User.get_by_username(u'test_user'), usr)
23 self.assertEqual(User.get_by_username(u'test_user'), usr)
24
24
25 # make users group
25 # make user group
26 users_group = UsersGroupModel().create('some_example_group')
26 users_group = UserGroupModel().create('some_example_group')
27 Session().commit()
27 Session().commit()
28
28
29 UsersGroupModel().add_user_to_group(users_group, usr)
29 UserGroupModel().add_user_to_group(users_group, usr)
30 Session().commit()
30 Session().commit()
31
31
32 self.assertEqual(UsersGroup.get(users_group.users_group_id), users_group)
32 self.assertEqual(UserGroup.get(users_group.users_group_id), users_group)
33 self.assertEqual(UsersGroupMember.query().count(), 1)
33 self.assertEqual(UserGroupMember.query().count(), 1)
34 UserModel().delete(usr.user_id)
34 UserModel().delete(usr.user_id)
35 Session().commit()
35 Session().commit()
36
36
37 self.assertEqual(UsersGroupMember.query().all(), [])
37 self.assertEqual(UserGroupMember.query().all(), [])
38
38
39 def test_additonal_email_as_main(self):
39 def test_additonal_email_as_main(self):
40 usr = UserModel().create_or_update(username=u'test_user',
40 usr = UserModel().create_or_update(username=u'test_user',
@@ -10,7 +10,7 b' from rhodecode.model.meta import Session'
10 from nose.tools import with_setup
10 from nose.tools import with_setup
11 from rhodecode.tests.models.common import _create_project_tree, check_tree_perms, \
11 from rhodecode.tests.models.common import _create_project_tree, check_tree_perms, \
12 _get_perms, _check_expected_count, expected_count, _destroy_project_tree
12 _get_perms, _check_expected_count, expected_count, _destroy_project_tree
13 from rhodecode.model.users_group import UsersGroupModel
13 from rhodecode.model.users_group import UserGroupModel
14 from rhodecode.model.repo import RepoModel
14 from rhodecode.model.repo import RepoModel
15
15
16
16
@@ -40,10 +40,10 b' def setup_module():'
40 Session().commit()
40 Session().commit()
41 test_u2_id = test_u2.user_id
41 test_u2_id = test_u2.user_id
42
42
43 gr1 = UsersGroupModel().create(name='perms_group_1')
43 gr1 = UserGroupModel().create(name='perms_group_1')
44 Session().commit()
44 Session().commit()
45 test_u2_gr_id = gr1.users_group_id
45 test_u2_gr_id = gr1.users_group_id
46 UsersGroupModel().add_user_to_group(gr1, user=test_u2_id)
46 UserGroupModel().add_user_to_group(gr1, user=test_u2_id)
47 Session().commit()
47 Session().commit()
48
48
49 _get_repo_perms = functools.partial(_get_perms, key='repositories',
49 _get_repo_perms = functools.partial(_get_perms, key='repositories',
@@ -209,6 +209,21 b' class TestLibs(unittest.TestCase):'
209 grav = gravatar_url(email_address=em, size=24)
209 grav = gravatar_url(email_address=em, size=24)
210 assert grav == 'https://server.com/%s/%s' % (_md5(em), 24)
210 assert grav == 'https://server.com/%s/%s' % (_md5(em), 24)
211
211
212 def _quick_url(self, text, tmpl="""<a class="revision-link" href="%s">%s</a>""", url_=None):
213 """
214 Changes `some text url[foo]` => `some text <a href="/">foo</a>
215
216 :param text:
217 """
218 import re
219 #quickly change expected url[] into a link
220 URL_PAT = re.compile(r'(?:url\[)(.+?)(?:\])')
221
222 def url_func(match_obj):
223 _url = match_obj.groups()[0]
224 return tmpl % (url_ or '/some-url', _url)
225 return URL_PAT.sub(url_func, text)
226
212 @parameterized.expand([
227 @parameterized.expand([
213 ("",
228 ("",
214 ""),
229 ""),
@@ -228,27 +243,48 b' class TestLibs(unittest.TestCase):'
228 "url[ffffffffffff] some text traalaa"),
243 "url[ffffffffffff] some text traalaa"),
229 ("""Multi line
244 ("""Multi line
230 123123123123
245 123123123123
231 some text 123123123123""",
246 some text 123123123123
247 sometimes !
248 """,
232 """Multi line
249 """Multi line
233 url[123123123123]
250 url[123123123123]
234 some text url[123123123123]""")
251 some text url[123123123123]
252 sometimes !
253 """)
235 ])
254 ])
236 def test_urlify_changesets(self, sample, expected):
255 def test_urlify_changesets(self, sample, expected):
237 import re
238
239 def fake_url(self, *args, **kwargs):
256 def fake_url(self, *args, **kwargs):
240 return '/some-url'
257 return '/some-url'
241
258
242 #quickly change expected url[] into a link
259 expected = self._quick_url(expected)
243 URL_PAT = re.compile(r'(?:url\[)(.+?)(?:\])')
244
245 def url_func(match_obj):
246 _url = match_obj.groups()[0]
247 tmpl = """<a class="revision-link" href="/some-url">%s</a>"""
248 return tmpl % _url
249
250 expected = URL_PAT.sub(url_func, expected)
251
260
252 with mock.patch('pylons.url', fake_url):
261 with mock.patch('pylons.url', fake_url):
253 from rhodecode.lib.helpers import urlify_changesets
262 from rhodecode.lib.helpers import urlify_changesets
254 self.assertEqual(urlify_changesets(sample, 'repo_name'), expected)
263 self.assertEqual(urlify_changesets(sample, 'repo_name'), expected)
264
265 @parameterized.expand([
266 ("",
267 "",
268 ""),
269 ("https://svn.apache.org/repos",
270 "url[https://svn.apache.org/repos]",
271 "https://svn.apache.org/repos"),
272 ("http://svn.apache.org/repos",
273 "url[http://svn.apache.org/repos]",
274 "http://svn.apache.org/repos"),
275 ("from rev a also rev http://google.com",
276 "from rev a also rev url[http://google.com]",
277 "http://google.com"),
278 ("""Multi line
279 https://foo.bar.com
280 some text lalala""",
281 """Multi line
282 url[https://foo.bar.com]
283 some text lalala""",
284 "https://foo.bar.com")
285 ])
286 def test_urlify_test(self, sample, expected, url_):
287 from rhodecode.lib.helpers import urlify_text
288 expected = self._quick_url(expected,
289 tmpl="""<a href="%s">%s</a>""", url_=url_)
290 self.assertEqual(urlify_text(sample), expected)
@@ -5,7 +5,7 b' import formencode'
5 from rhodecode.tests import *
5 from rhodecode.tests import *
6
6
7 from rhodecode.model import validators as v
7 from rhodecode.model import validators as v
8 from rhodecode.model.users_group import UsersGroupModel
8 from rhodecode.model.users_group import UserGroupModel
9
9
10 from rhodecode.model.meta import Session
10 from rhodecode.model.meta import Session
11 from rhodecode.model.repos_group import ReposGroupModel
11 from rhodecode.model.repos_group import ReposGroupModel
@@ -51,25 +51,25 b' class TestReposGroups(unittest.TestCase)'
51 self.assertEqual(TEST_USER_ADMIN_LOGIN,
51 self.assertEqual(TEST_USER_ADMIN_LOGIN,
52 validator.to_python(TEST_USER_ADMIN_LOGIN))
52 validator.to_python(TEST_USER_ADMIN_LOGIN))
53
53
54 def test_ValidUsersGroup(self):
54 def test_ValidUserGroup(self):
55 validator = v.ValidUsersGroup()
55 validator = v.ValidUserGroup()
56 self.assertRaises(formencode.Invalid, validator.to_python, 'default')
56 self.assertRaises(formencode.Invalid, validator.to_python, 'default')
57 self.assertRaises(formencode.Invalid, validator.to_python, '.,')
57 self.assertRaises(formencode.Invalid, validator.to_python, '.,')
58
58
59 gr = UsersGroupModel().create('test')
59 gr = UserGroupModel().create('test')
60 gr2 = UsersGroupModel().create('tes2')
60 gr2 = UserGroupModel().create('tes2')
61 Session.commit()
61 Session.commit()
62 self.assertRaises(formencode.Invalid, validator.to_python, 'test')
62 self.assertRaises(formencode.Invalid, validator.to_python, 'test')
63 assert gr.users_group_id != None
63 assert gr.users_group_id != None
64 validator = v.ValidUsersGroup(edit=True,
64 validator = v.ValidUserGroup(edit=True,
65 old_data={'users_group_id':
65 old_data={'users_group_id':
66 gr2.users_group_id})
66 gr2.users_group_id})
67
67
68 self.assertRaises(formencode.Invalid, validator.to_python, 'test')
68 self.assertRaises(formencode.Invalid, validator.to_python, 'test')
69 self.assertRaises(formencode.Invalid, validator.to_python, 'TesT')
69 self.assertRaises(formencode.Invalid, validator.to_python, 'TesT')
70 self.assertRaises(formencode.Invalid, validator.to_python, 'TEST')
70 self.assertRaises(formencode.Invalid, validator.to_python, 'TEST')
71 UsersGroupModel().delete(gr)
71 UserGroupModel().delete(gr)
72 UsersGroupModel().delete(gr2)
72 UserGroupModel().delete(gr2)
73 Session.commit()
73 Session.commit()
74
74
75 def test_ValidReposGroup(self):
75 def test_ValidReposGroup(self):
@@ -35,11 +35,12 b' is_windows = __platform__ in _get_meta_v'
35 requirements = [
35 requirements = [
36 "waitress==0.8.2",
36 "waitress==0.8.2",
37 "webob==1.0.8",
37 "webob==1.0.8",
38 "webtest==1.4.3",
38 "Pylons==1.0.0",
39 "Pylons==1.0.0",
39 "Beaker==1.6.4",
40 "Beaker==1.6.4",
40 "WebHelpers==1.3",
41 "WebHelpers==1.3",
41 "formencode==1.2.4",
42 "formencode==1.2.4",
42 "SQLAlchemy==0.7.9",
43 "SQLAlchemy==0.7.10",
43 "Mako==0.7.3",
44 "Mako==0.7.3",
44 "pygments>=1.5",
45 "pygments>=1.5",
45 "whoosh>=2.4.0,<2.5",
46 "whoosh>=2.4.0,<2.5",
1 NO CONTENT: file was removed
NO CONTENT: file was removed
General Comments 0
You need to be logged in to leave comments. Login now