diff --git a/rhodecode/apps/ssh_support/lib/backends/__init__.py b/rhodecode/apps/ssh_support/lib/backends/__init__.py --- a/rhodecode/apps/ssh_support/lib/backends/__init__.py +++ b/rhodecode/apps/ssh_support/lib/backends/__init__.py @@ -23,8 +23,9 @@ import re import logging import datetime import configparser +from sqlalchemy import Table -from rhodecode.model.db import Session, User, UserSshKeys +from rhodecode.lib.utils2 import AttributeDict from rhodecode.model.scm import ScmModel from .hg import MercurialServer @@ -39,11 +40,11 @@ class SshWrapper(object): svn_cmd_pat = re.compile(r'^svnserve -t') def __init__(self, command, connection_info, mode, - user, user_id, key_id, shell, ini_path, env): + user, user_id, key_id: int, shell, ini_path: str, env): self.command = command self.connection_info = connection_info self.mode = mode - self.user = user + self.username = user self.user_id = user_id self.key_id = key_id self.shell = shell @@ -59,14 +60,38 @@ class SshWrapper(object): return parser def update_key_access_time(self, key_id): - key = UserSshKeys().query().filter( - UserSshKeys.ssh_key_id == key_id).scalar() - if key: - key.accessed_on = datetime.datetime.utcnow() - Session().add(key) - Session().commit() + from rhodecode.model.meta import raw_query_executor, Base + + table = Table('user_ssh_keys', Base.metadata, autoload=False) + stmt = ( + table.update() + .where(table.c.ssh_key_id == key_id) + .values(accessed_on=datetime.datetime.utcnow()) + .returning(table.c.accessed_on, table.c.ssh_key_fingerprint) + ) + + scalar_res = None + with raw_query_executor() as session: + result = session.execute(stmt) + if result.rowcount: + scalar_res = result.first() + + if scalar_res: + atime, ssh_key_fingerprint = scalar_res log.debug('Update key id:`%s` fingerprint:`%s` access time', - key_id, key.ssh_key_fingerprint) + key_id, ssh_key_fingerprint) + + def get_user(self, user_id): + user = AttributeDict() + # lazy load db imports + from rhodecode.model.db import User + dbuser = User.get(user_id) + if not dbuser: + return None + user.user_id = dbuser.user_id + user.username = dbuser.username + user.auth_user = dbuser.AuthUser() + return user def get_connection_info(self): """ @@ -186,7 +211,7 @@ class SshWrapper(object): def wrap(self): mode = self.mode - user = self.user + username = self.username user_id = self.user_id key_id = self.key_id shell = self.shell @@ -194,15 +219,16 @@ class SshWrapper(object): scm_detected, scm_repo, scm_mode = self.get_repo_details(mode) log.debug( - 'Mode: `%s` User: `%s:%s` Shell: `%s` SSH Command: `\"%s\"` ' + 'Mode: `%s` User: `name:%s : id:%s` Shell: `%s` SSH Command: `\"%s\"` ' 'SCM_DETECTED: `%s` SCM Mode: `%s` SCM Repo: `%s`', - mode, user, user_id, shell, self.command, + mode, username, user_id, shell, self.command, scm_detected, scm_mode, scm_repo) + log.debug('SSH Connection info %s', self.get_connection_info()) + # update last access time for this key - self.update_key_access_time(key_id) - - log.debug('SSH Connection info %s', self.get_connection_info()) + if key_id: + self.update_key_access_time(key_id) if shell and self.command is None: log.info('Dropping to shell, no command given and shell is allowed') @@ -210,13 +236,13 @@ class SshWrapper(object): exit_code = 1 elif scm_detected: - user = User.get(user_id) + user = self.get_user(user_id) if not user: log.warning('User with id %s not found', user_id) exit_code = -1 return exit_code - auth_user = user.AuthUser() + auth_user = user.auth_user permissions = auth_user.permissions['repositories'] repo_branch_permissions = auth_user.get_branch_permissions(scm_repo) try: diff --git a/rhodecode/model/meta.py b/rhodecode/model/meta.py --- a/rhodecode/model/meta.py +++ b/rhodecode/model/meta.py @@ -24,10 +24,10 @@ SQLAlchemy Metadata and Session object from sqlalchemy.orm import declarative_base from sqlalchemy.orm import scoped_session, sessionmaker - +from sqlalchemy.orm import Session as SASession from rhodecode.lib import caching_query -__all__ = ['Base', 'Session'] +__all__ = ['Base', 'Session', 'raw_query_executor'] # scoped_session. Apply our custom CachingQuery class to it, # using a callable that will associate the dictionary @@ -43,3 +43,9 @@ Session = scoped_session( # The declarative Base Base = declarative_base() + + +def raw_query_executor(): + engine = Base.metadata.bind + session = SASession(engine) + return session