import time import logging import functools from pyramid.httpexceptions import HTTPFound from rhodecode.lib import helpers as h from rhodecode.model.meta import Session log = logging.getLogger(__name__) SUDO_GRACE_PERIOD = 600 # 10 minutes class SudoOTPRequired(object): def __init__(self, func): functools.update_wrapper(self, func) self.func = func def __get__(self, obj, cls): return functools.partial(self.__call__, obj) def __call__(self, method_self, *args, **kwargs): session = method_self.request.session verified_at = session.get("sudo_otp_verified_at", 0) if (time.time() - verified_at) < SUDO_GRACE_PERIOD: return self.func(method_self, *args, **kwargs) # Need sudo verification — generate OTP and redirect user = method_self._rhodecode_db_user code = user.generate_otp("sudo", digits=8) Session().commit() import rhodecode smtp_server = rhodecode.CONFIG.get('smtp_server') log_code = code if not smtp_server else 'X' * len(code) log.info('[OTP] code=%s email=%s purpose=sudo', log_code, user.email) # Send OTP email from rhodecode.lib.celerylib import tasks, run_task from rhodecode.model.notification import EmailNotificationModel email_kwargs = { 'otp_code': code, 'purpose': 'sudo', } (subject, email_body, email_body_plaintext) = EmailNotificationModel().render_email( EmailNotificationModel.TYPE_OTP_CODE, **email_kwargs ) run_task(tasks.send_email, [user.email], subject, email_body_plaintext, email_body) # Store where to go after verification session["sudo_next_url"] = method_self.request.url if hasattr(session, 'save'): session.save() raise HTTPFound(method_self.request.route_path("sudo_otp_verify"))