Show More
The requested changes are too big and content was truncated. Show full diff
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
@@ -0,0 +1,35 b'' | |||||
|
1 | # -*- coding: utf-8 -*- | |||
|
2 | ||||
|
3 | import logging | |||
|
4 | from sqlalchemy import * | |||
|
5 | ||||
|
6 | from alembic.migration import MigrationContext | |||
|
7 | from alembic.operations import Operations | |||
|
8 | from sqlalchemy import BigInteger | |||
|
9 | ||||
|
10 | from rhodecode.lib.dbmigrate.versions import _reset_base | |||
|
11 | from rhodecode.model import init_model_encryption | |||
|
12 | ||||
|
13 | ||||
|
14 | log = logging.getLogger(__name__) | |||
|
15 | ||||
|
16 | ||||
|
17 | def upgrade(migrate_engine): | |||
|
18 | """ | |||
|
19 | Upgrade operations go here. | |||
|
20 | Don't create your own engine; bind migrate_engine to your metadata | |||
|
21 | """ | |||
|
22 | _reset_base(migrate_engine) | |||
|
23 | from rhodecode.lib.dbmigrate.schema import db_4_19_0_0 as db | |||
|
24 | ||||
|
25 | init_model_encryption(db) | |||
|
26 | db.UserNotice().__table__.create() | |||
|
27 | ||||
|
28 | ||||
|
29 | def downgrade(migrate_engine): | |||
|
30 | meta = MetaData() | |||
|
31 | meta.bind = migrate_engine | |||
|
32 | ||||
|
33 | ||||
|
34 | def fixups(models, _SESSION): | |||
|
35 | pass |
@@ -45,7 +45,7 b' PYRAMID_SETTINGS = {}' | |||||
45 | EXTENSIONS = {} |
|
45 | EXTENSIONS = {} | |
46 |
|
46 | |||
47 | __version__ = ('.'.join((str(each) for each in VERSION[:3]))) |
|
47 | __version__ = ('.'.join((str(each) for each in VERSION[:3]))) | |
48 |
__dbversion__ = 10 |
|
48 | __dbversion__ = 105 # defines current db version for migrations | |
49 | __platform__ = platform.system() |
|
49 | __platform__ = platform.system() | |
50 | __license__ = 'AGPLv3, and Commercial License' |
|
50 | __license__ = 'AGPLv3, and Commercial License' | |
51 | __author__ = 'RhodeCode GmbH' |
|
51 | __author__ = 'RhodeCode GmbH' |
@@ -26,7 +26,6 b' def admin_routes(config):' | |||||
26 | """ |
|
26 | """ | |
27 | Admin prefixed routes |
|
27 | Admin prefixed routes | |
28 | """ |
|
28 | """ | |
29 |
|
||||
30 | config.add_route( |
|
29 | config.add_route( | |
31 | name='admin_audit_logs', |
|
30 | name='admin_audit_logs', | |
32 | pattern='/audit_logs') |
|
31 | pattern='/audit_logs') | |
@@ -291,6 +290,12 b' def admin_routes(config):' | |||||
291 | pattern='/users/{user_id:\d+}/create_repo_group', |
|
290 | pattern='/users/{user_id:\d+}/create_repo_group', | |
292 | user_route=True) |
|
291 | user_route=True) | |
293 |
|
292 | |||
|
293 | # user notice | |||
|
294 | config.add_route( | |||
|
295 | name='user_notice_dismiss', | |||
|
296 | pattern='/users/{user_id:\d+}/notice_dismiss', | |||
|
297 | user_route=True) | |||
|
298 | ||||
294 | # user auth tokens |
|
299 | # user auth tokens | |
295 | config.add_route( |
|
300 | config.add_route( | |
296 | name='edit_user_auth_tokens', |
|
301 | name='edit_user_auth_tokens', |
@@ -34,7 +34,7 b' from rhodecode.apps.ssh_support import S' | |||||
34 | from rhodecode.authentication.base import get_authn_registry, RhodeCodeExternalAuthPlugin |
|
34 | from rhodecode.authentication.base import get_authn_registry, RhodeCodeExternalAuthPlugin | |
35 | from rhodecode.authentication.plugins import auth_rhodecode |
|
35 | from rhodecode.authentication.plugins import auth_rhodecode | |
36 | from rhodecode.events import trigger |
|
36 | from rhodecode.events import trigger | |
37 | from rhodecode.model.db import true |
|
37 | from rhodecode.model.db import true, UserNotice | |
38 |
|
38 | |||
39 | from rhodecode.lib import audit_logger, rc_cache |
|
39 | from rhodecode.lib import audit_logger, rc_cache | |
40 | from rhodecode.lib.exceptions import ( |
|
40 | from rhodecode.lib.exceptions import ( | |
@@ -705,6 +705,32 b' class UsersView(UserAppView):' | |||||
705 | @HasPermissionAllDecorator('hg.admin') |
|
705 | @HasPermissionAllDecorator('hg.admin') | |
706 | @CSRFRequired() |
|
706 | @CSRFRequired() | |
707 | @view_config( |
|
707 | @view_config( | |
|
708 | route_name='user_notice_dismiss', request_method='POST', | |||
|
709 | renderer='json_ext', xhr=True) | |||
|
710 | def user_notice_dismiss(self): | |||
|
711 | _ = self.request.translate | |||
|
712 | c = self.load_default_context() | |||
|
713 | ||||
|
714 | user_id = self.db_user_id | |||
|
715 | c.user = self.db_user | |||
|
716 | user_notice_id = safe_int(self.request.POST.get('notice_id')) | |||
|
717 | notice = UserNotice().query()\ | |||
|
718 | .filter(UserNotice.user_id == user_id)\ | |||
|
719 | .filter(UserNotice.user_notice_id == user_notice_id)\ | |||
|
720 | .scalar() | |||
|
721 | read = False | |||
|
722 | if notice: | |||
|
723 | notice.notice_read = True | |||
|
724 | Session().add(notice) | |||
|
725 | Session().commit() | |||
|
726 | read = True | |||
|
727 | ||||
|
728 | return {'notice': user_notice_id, 'read': read} | |||
|
729 | ||||
|
730 | @LoginRequired() | |||
|
731 | @HasPermissionAllDecorator('hg.admin') | |||
|
732 | @CSRFRequired() | |||
|
733 | @view_config( | |||
708 | route_name='user_create_personal_repo_group', request_method='POST', |
|
734 | route_name='user_create_personal_repo_group', request_method='POST', | |
709 | renderer='rhodecode:templates/admin/users/user_edit.mako') |
|
735 | renderer='rhodecode:templates/admin/users/user_edit.mako') | |
710 | def user_create_personal_repo_group(self): |
|
736 | def user_create_personal_repo_group(self): |
@@ -23,6 +23,8 b' authentication and permission libraries' | |||||
23 | """ |
|
23 | """ | |
24 |
|
24 | |||
25 | import os |
|
25 | import os | |
|
26 | ||||
|
27 | import colander | |||
26 | import time |
|
28 | import time | |
27 | import collections |
|
29 | import collections | |
28 | import fnmatch |
|
30 | import fnmatch | |
@@ -45,15 +47,14 b' from rhodecode.model import meta' | |||||
45 | from rhodecode.model.meta import Session |
|
47 | from rhodecode.model.meta import Session | |
46 | from rhodecode.model.user import UserModel |
|
48 | from rhodecode.model.user import UserModel | |
47 | from rhodecode.model.db import ( |
|
49 | from rhodecode.model.db import ( | |
48 | User, Repository, Permission, UserToPerm, UserGroupToPerm, UserGroupMember, |
|
50 | false, User, Repository, Permission, UserToPerm, UserGroupToPerm, UserGroupMember, | |
49 | UserIpMap, UserApiKeys, RepoGroup, UserGroup) |
|
51 | UserIpMap, UserApiKeys, RepoGroup, UserGroup, UserNotice) | |
50 | from rhodecode.lib import rc_cache |
|
52 | from rhodecode.lib import rc_cache | |
51 | from rhodecode.lib.utils2 import safe_unicode, aslist, safe_str, md5, safe_int, sha1 |
|
53 | from rhodecode.lib.utils2 import safe_unicode, aslist, safe_str, md5, safe_int, sha1 | |
52 | from rhodecode.lib.utils import ( |
|
54 | from rhodecode.lib.utils import ( | |
53 | get_repo_slug, get_repo_group_slug, get_user_group_slug) |
|
55 | get_repo_slug, get_repo_group_slug, get_user_group_slug) | |
54 | from rhodecode.lib.caching_query import FromCache |
|
56 | from rhodecode.lib.caching_query import FromCache | |
55 |
|
57 | |||
56 |
|
||||
57 | if rhodecode.is_unix: |
|
58 | if rhodecode.is_unix: | |
58 | import bcrypt |
|
59 | import bcrypt | |
59 |
|
60 | |||
@@ -1455,6 +1456,38 b' class AuthUser(object):' | |||||
1455 |
|
1456 | |||
1456 | return rule, default_perm |
|
1457 | return rule, default_perm | |
1457 |
|
1458 | |||
|
1459 | def get_notice_messages(self): | |||
|
1460 | ||||
|
1461 | notice_level = 'notice-error' | |||
|
1462 | notice_messages = [] | |||
|
1463 | if self.is_default: | |||
|
1464 | return [], notice_level | |||
|
1465 | ||||
|
1466 | notices = UserNotice.query()\ | |||
|
1467 | .filter(UserNotice.user_id == self.user_id)\ | |||
|
1468 | .filter(UserNotice.notice_read == false())\ | |||
|
1469 | .all() | |||
|
1470 | ||||
|
1471 | try: | |||
|
1472 | for entry in notices: | |||
|
1473 | ||||
|
1474 | msg = { | |||
|
1475 | 'msg_id': entry.user_notice_id, | |||
|
1476 | 'level': entry.notification_level, | |||
|
1477 | 'subject': entry.notice_subject, | |||
|
1478 | 'body': entry.notice_body, | |||
|
1479 | } | |||
|
1480 | notice_messages.append(msg) | |||
|
1481 | ||||
|
1482 | log.debug('Got user %s %s messages', self, len(notice_messages)) | |||
|
1483 | ||||
|
1484 | levels = [x['level'] for x in notice_messages] | |||
|
1485 | notice_level = 'notice-error' if 'error' in levels else 'notice-warning' | |||
|
1486 | except Exception: | |||
|
1487 | pass | |||
|
1488 | ||||
|
1489 | return notice_messages, notice_level | |||
|
1490 | ||||
1458 | def __repr__(self): |
|
1491 | def __repr__(self): | |
1459 | return "<AuthUser('id:%s[%s] ip:%s auth:%s')>"\ |
|
1492 | return "<AuthUser('id:%s[%s] ip:%s auth:%s')>"\ | |
1460 | % (self.user_id, self.username, self.ip_addr, self.is_authenticated) |
|
1493 | % (self.user_id, self.username, self.ip_addr, self.is_authenticated) |
@@ -4517,6 +4517,65 b' class UserNotification(Base, BaseModel):' | |||||
4517 | Session().add(self) |
|
4517 | Session().add(self) | |
4518 |
|
4518 | |||
4519 |
|
4519 | |||
|
4520 | class UserNotice(Base, BaseModel): | |||
|
4521 | __tablename__ = 'user_notices' | |||
|
4522 | __table_args__ = ( | |||
|
4523 | base_table_args | |||
|
4524 | ) | |||
|
4525 | ||||
|
4526 | NOTIFICATION_TYPE_MESSAGE = 'message' | |||
|
4527 | NOTIFICATION_TYPE_NOTICE = 'notice' | |||
|
4528 | ||||
|
4529 | NOTIFICATION_LEVEL_INFO = 'info' | |||
|
4530 | NOTIFICATION_LEVEL_WARNING = 'warning' | |||
|
4531 | NOTIFICATION_LEVEL_ERROR = 'error' | |||
|
4532 | ||||
|
4533 | user_notice_id = Column('gist_id', Integer(), primary_key=True) | |||
|
4534 | ||||
|
4535 | notice_subject = Column('notice_subject', Unicode(512), nullable=True) | |||
|
4536 | notice_body = Column('notice_body', UnicodeText().with_variant(UnicodeText(50000), 'mysql'), nullable=True) | |||
|
4537 | ||||
|
4538 | notice_read = Column('notice_read', Boolean, default=False) | |||
|
4539 | ||||
|
4540 | notification_level = Column('notification_level', String(1024), default=NOTIFICATION_LEVEL_INFO) | |||
|
4541 | notification_type = Column('notification_type', String(1024), default=NOTIFICATION_TYPE_NOTICE) | |||
|
4542 | ||||
|
4543 | notice_created_by = Column('notice_created_by', Integer(), ForeignKey('users.user_id'), nullable=True) | |||
|
4544 | notice_created_on = Column('notice_created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now) | |||
|
4545 | ||||
|
4546 | user_id = Column('user_id', Integer(), ForeignKey('users.user_id')) | |||
|
4547 | user = relationship('User', lazy="joined", primaryjoin='User.user_id==UserNotice.user_id') | |||
|
4548 | ||||
|
4549 | @classmethod | |||
|
4550 | def create_for_user(cls, user, subject, body, notice_level=NOTIFICATION_LEVEL_INFO, allow_duplicate=False): | |||
|
4551 | ||||
|
4552 | if notice_level not in [cls.NOTIFICATION_LEVEL_ERROR, | |||
|
4553 | cls.NOTIFICATION_LEVEL_WARNING, | |||
|
4554 | cls.NOTIFICATION_LEVEL_INFO]: | |||
|
4555 | return | |||
|
4556 | ||||
|
4557 | from rhodecode.model.user import UserModel | |||
|
4558 | user = UserModel().get_user(user) | |||
|
4559 | ||||
|
4560 | new_notice = UserNotice() | |||
|
4561 | if not allow_duplicate: | |||
|
4562 | existing_msg = UserNotice().query() \ | |||
|
4563 | .filter(UserNotice.user == user) \ | |||
|
4564 | .filter(UserNotice.notice_body == body) \ | |||
|
4565 | .filter(UserNotice.notice_read == false()) \ | |||
|
4566 | .scalar() | |||
|
4567 | if existing_msg: | |||
|
4568 | log.warning('Ignoring duplicate notice for user %s', user) | |||
|
4569 | return | |||
|
4570 | ||||
|
4571 | new_notice.user = user | |||
|
4572 | new_notice.notice_subject = subject | |||
|
4573 | new_notice.notice_body = body | |||
|
4574 | new_notice.notification_level = notice_level | |||
|
4575 | Session().add(new_notice) | |||
|
4576 | Session().commit() | |||
|
4577 | ||||
|
4578 | ||||
4520 | class Gist(Base, BaseModel): |
|
4579 | class Gist(Base, BaseModel): | |
4521 | __tablename__ = 'gists' |
|
4580 | __tablename__ = 'gists' | |
4522 | __table_args__ = ( |
|
4581 | __table_args__ = ( |
@@ -2101,6 +2101,12 b' BIN_FILENODE = 7' | |||||
2101 | } |
|
2101 | } | |
2102 | } |
|
2102 | } | |
2103 |
|
2103 | |||
|
2104 | .notice-messages { | |||
|
2105 | .markdown-block, | |||
|
2106 | .rst-block { | |||
|
2107 | padding: 0; | |||
|
2108 | } | |||
|
2109 | } | |||
2104 |
|
2110 | |||
2105 | .notifications_buttons{ |
|
2111 | .notifications_buttons{ | |
2106 | float: right; |
|
2112 | float: right; |
@@ -820,7 +820,53 b' input {' | |||||
820 | } |
|
820 | } | |
821 |
|
821 | |||
822 | .menulabel-notice { |
|
822 | .menulabel-notice { | |
823 | border: 1px solid @color5; |
|
823 | ||
824 | padding:7px 10px; |
|
824 | padding:7px 10px; | |
|
825 | ||||
|
826 | &.notice-warning { | |||
|
827 | border: 1px solid @color3; | |||
|
828 | .notice-color-warning | |||
|
829 | } | |||
|
830 | &.notice-error { | |||
|
831 | border: 1px solid @color5; | |||
|
832 | .notice-color-error | |||
|
833 | } | |||
|
834 | &.notice-info { | |||
|
835 | border: 1px solid @color1; | |||
|
836 | .notice-color-info | |||
|
837 | } | |||
|
838 | } | |||
|
839 | ||||
|
840 | .notice-messages-container { | |||
|
841 | position: absolute; | |||
|
842 | top: 45px; | |||
|
843 | } | |||
|
844 | ||||
|
845 | .notice-messages { | |||
|
846 | display: block; | |||
|
847 | position: relative; | |||
|
848 | z-index: 300; | |||
|
849 | min-width: 500px; | |||
|
850 | max-width: 500px; | |||
|
851 | min-height: 100px; | |||
|
852 | margin-top: 4px; | |||
|
853 | margin-bottom: 24px; | |||
|
854 | font-size: 14px; | |||
|
855 | font-weight: 400; | |||
|
856 | padding: 8px 0; | |||
|
857 | background-color: #fff; | |||
|
858 | border: 1px solid @grey4; | |||
|
859 | box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.07); | |||
|
860 | } | |||
|
861 | ||||
|
862 | .notice-color-warning { | |||
|
863 | color: @color3; | |||
|
864 | } | |||
|
865 | ||||
|
866 | .notice-color-error { | |||
825 | color: @color5; |
|
867 | color: @color5; | |
826 | } |
|
868 | } | |
|
869 | ||||
|
870 | .notice-color-info { | |||
|
871 | color: @color1; | |||
|
872 | } |
@@ -269,6 +269,7 b'' | |||||
269 | .icon-expand-linked { cursor: pointer; color: @grey3; font-size: 14px } |
|
269 | .icon-expand-linked { cursor: pointer; color: @grey3; font-size: 14px } | |
270 | .icon-more-linked { cursor: pointer; color: @grey3 } |
|
270 | .icon-more-linked { cursor: pointer; color: @grey3 } | |
271 | .icon-flag-filled-red { color: @color5 !important; } |
|
271 | .icon-flag-filled-red { color: @color5 !important; } | |
|
272 | .icon-filled-red { color: @color5 !important; } | |||
272 |
|
273 | |||
273 | .repo-switcher-dropdown .select2-result-label { |
|
274 | .repo-switcher-dropdown .select2-result-label { | |
274 | .icon-git:before { |
|
275 | .icon-git:before { |
@@ -110,6 +110,7 b' function registerRCRoutes() {' | |||||
110 | pyroutes.register('user_enable_force_password_reset', '/_admin/users/%(user_id)s/password_reset_enable', ['user_id']); |
|
110 | pyroutes.register('user_enable_force_password_reset', '/_admin/users/%(user_id)s/password_reset_enable', ['user_id']); | |
111 | pyroutes.register('user_disable_force_password_reset', '/_admin/users/%(user_id)s/password_reset_disable', ['user_id']); |
|
111 | pyroutes.register('user_disable_force_password_reset', '/_admin/users/%(user_id)s/password_reset_disable', ['user_id']); | |
112 | pyroutes.register('user_create_personal_repo_group', '/_admin/users/%(user_id)s/create_repo_group', ['user_id']); |
|
112 | pyroutes.register('user_create_personal_repo_group', '/_admin/users/%(user_id)s/create_repo_group', ['user_id']); | |
|
113 | pyroutes.register('user_notice_dismiss', '/_admin/users/%(user_id)s/notice_dismiss', ['user_id']); | |||
113 | pyroutes.register('edit_user_auth_tokens_delete', '/_admin/users/%(user_id)s/edit/auth_tokens/delete', ['user_id']); |
|
114 | pyroutes.register('edit_user_auth_tokens_delete', '/_admin/users/%(user_id)s/edit/auth_tokens/delete', ['user_id']); | |
114 | pyroutes.register('edit_user_ssh_keys', '/_admin/users/%(user_id)s/edit/ssh_keys', ['user_id']); |
|
115 | pyroutes.register('edit_user_ssh_keys', '/_admin/users/%(user_id)s/edit/ssh_keys', ['user_id']); | |
115 | pyroutes.register('edit_user_ssh_keys_generate_keypair', '/_admin/users/%(user_id)s/edit/ssh_keys/generate', ['user_id']); |
|
116 | pyroutes.register('edit_user_ssh_keys_generate_keypair', '/_admin/users/%(user_id)s/edit/ssh_keys/generate', ['user_id']); |
@@ -688,17 +688,50 b'' | |||||
688 | </%def> |
|
688 | </%def> | |
689 |
|
689 | |||
690 | <%def name="menu_items(active=None)"> |
|
690 | <%def name="menu_items(active=None)"> | |
|
691 | <% | |||
|
692 | notice_messages, notice_level = c.rhodecode_user.get_notice_messages() | |||
|
693 | notice_display = 'none' if len(notice_messages) == 0 else '' | |||
|
694 | %> | |||
|
695 | <style> | |||
|
696 | ||||
|
697 | </style> | |||
691 |
|
698 | |||
692 | <ul id="quick" class="main_nav navigation horizontal-list"> |
|
699 | <ul id="quick" class="main_nav navigation horizontal-list"> | |
693 | ## notice box for important system messages |
|
700 | ## notice box for important system messages | |
694 |
<li style="display: |
|
701 | <li style="display: ${notice_display}"> | |
695 | <a class="notice-box" href="#openNotice" onclick="return false"> |
|
702 | <a class="notice-box" href="#openNotice" onclick="$('.notice-messages-container').toggle(); return false"> | |
696 | <div class="menulabel-notice" > |
|
703 | <div class="menulabel-notice ${notice_level}" > | |
697 | 0 |
|
704 | ${len(notice_messages)} | |
698 | </div> |
|
705 | </div> | |
699 | </a> |
|
706 | </a> | |
700 | </li> |
|
707 | </li> | |
|
708 | <div class="notice-messages-container" style="display: none"> | |||
|
709 | <div class="notice-messages"> | |||
|
710 | <table class="rctable"> | |||
|
711 | % for notice in notice_messages: | |||
|
712 | <tr id="notice-message-${notice['msg_id']}" class="notice-message-${notice['level']}"> | |||
|
713 | <td style="vertical-align: text-top; width: 20px"> | |||
|
714 | <i class="tooltip icon-info notice-color-${notice['level']}" title="${notice['level']}"></i> | |||
|
715 | </td> | |||
|
716 | <td> | |||
|
717 | <span><i class="icon-plus-squared cursor-pointer" onclick="$('#notice-${notice['msg_id']}').toggle()"></i> </span> | |||
|
718 | ${notice['subject']} | |||
701 |
|
719 | |||
|
720 | <div id="notice-${notice['msg_id']}" style="display: none"> | |||
|
721 | ${h.render(notice['body'], renderer='markdown')} | |||
|
722 | </div> | |||
|
723 | </td> | |||
|
724 | <td style="vertical-align: text-top; width: 35px;"> | |||
|
725 | <a class="tooltip" title="${_('dismiss')}" href="#dismiss" onclick="dismissNotice(${notice['msg_id']});return false"> | |||
|
726 | <i class="icon-remove icon-filled-red"></i> | |||
|
727 | </a> | |||
|
728 | </td> | |||
|
729 | </tr> | |||
|
730 | ||||
|
731 | % endfor | |||
|
732 | </table> | |||
|
733 | </div> | |||
|
734 | </div> | |||
702 | ## Main filter |
|
735 | ## Main filter | |
703 | <li> |
|
736 | <li> | |
704 | <div class="menulabel main_filter_box"> |
|
737 | <div class="menulabel main_filter_box"> | |
@@ -1058,6 +1091,26 b'' | |||||
1058 | } |
|
1091 | } | |
1059 | }); |
|
1092 | }); | |
1060 |
|
1093 | |||
|
1094 | var dismissNotice = function(noticeId) { | |||
|
1095 | ||||
|
1096 | var url = pyroutes.url('user_notice_dismiss', | |||
|
1097 | {"user_id": templateContext.rhodecode_user.user_id}); | |||
|
1098 | ||||
|
1099 | var postData = { | |||
|
1100 | 'csrf_token': CSRF_TOKEN, | |||
|
1101 | 'notice_id': noticeId, | |||
|
1102 | }; | |||
|
1103 | ||||
|
1104 | var success = function(response) { | |||
|
1105 | $('#notice-message-' + noticeId).remove(); | |||
|
1106 | return false; | |||
|
1107 | }; | |||
|
1108 | var failure = function(data, textStatus, xhr) { | |||
|
1109 | alert("error processing request: " + textStatus); | |||
|
1110 | return false; | |||
|
1111 | }; | |||
|
1112 | ajaxPOST(url, postData, success, failure); | |||
|
1113 | } | |||
1061 | </script> |
|
1114 | </script> | |
1062 | <script src="${h.asset('js/rhodecode/base/keyboard-bindings.js', ver=c.rhodecode_version_hash)}"></script> |
|
1115 | <script src="${h.asset('js/rhodecode/base/keyboard-bindings.js', ver=c.rhodecode_version_hash)}"></script> | |
1063 | </%def> |
|
1116 | </%def> |
@@ -15,6 +15,7 b" if getattr(c, 'repo_group', None):" | |||||
15 | c.template_context['repo_group_name'] = c.repo_group.group_name |
|
15 | c.template_context['repo_group_name'] = c.repo_group.group_name | |
16 |
|
16 | |||
17 | if getattr(c, 'rhodecode_user', None) and c.rhodecode_user.user_id: |
|
17 | if getattr(c, 'rhodecode_user', None) and c.rhodecode_user.user_id: | |
|
18 | c.template_context['rhodecode_user']['user_id'] = c.rhodecode_user.user_id | |||
18 | c.template_context['rhodecode_user']['username'] = c.rhodecode_user.username |
|
19 | c.template_context['rhodecode_user']['username'] = c.rhodecode_user.username | |
19 | c.template_context['rhodecode_user']['email'] = c.rhodecode_user.email |
|
20 | c.template_context['rhodecode_user']['email'] = c.rhodecode_user.email | |
20 | c.template_context['rhodecode_user']['notification_status'] = c.rhodecode_user.get_instance().user_data.get('notification_status', True) |
|
21 | c.template_context['rhodecode_user']['notification_status'] = c.rhodecode_user.get_instance().user_data.get('notification_status', True) |
General Comments 0
You need to be logged in to leave comments.
Login now