Fix session.save() for cookie sessions, add vcsserver/rc_license stubs

- Guard all session.save() calls with hasattr checks for CookieSession
  compatibility (CookieSession auto-saves via response callbacks)
- Guard beaker-specific _set_cookie_expires and _update_cookie_out in
  login views
- Defer ldap scope_labels to property to avoid class-level AttributeError
  when python-ldap is not installed
- Add vcsserver stub package to allow imports without full vcsserver
- Add rc_license stub for CE edition (no license management)
This commit is contained in:
russell@unturf.com 2026-02-19 19:38:09 -05:00
parent 784a89fc9e
commit dc3502fed0
10 changed files with 46 additions and 10 deletions

View file

@ -73,18 +73,20 @@ def store_user_in_session(session, user_identifier, remember=False):
Session().commit()
# If they want to be remembered, update the cookie
if remember:
if remember and hasattr(session, '_set_cookie_expires'):
_year = datetime.datetime.now() + datetime.timedelta(seconds=60 * 60 * 24 * 365)
session._set_cookie_expires(_year)
session.save()
if hasattr(session, 'save'):
session.save()
safe_cs = cs.copy()
safe_cs["password"] = "****"
log.info("user %s is now authenticated and stored in session, session attrs %s", user_identifier, safe_cs)
# dumps session attrs back to cookie
session._update_cookie_out()
if hasattr(session, '_update_cookie_out'):
session._update_cookie_out()
# we set new cookie
headers = None
if session.request["set_cookie"]:

View file

@ -204,7 +204,8 @@ class MyAccountView(BaseAppView, DataGridAppView):
else:
instance = c.auth_user.get_instance()
self.session.setdefault("rhodecode_user", {}).update({"password": md5_safe(instance.password)})
self.session.save()
if hasattr(self.session, 'save'):
self.session.save()
h.flash(_("Successfully updated password"), category="success")
raise HTTPFound(self.request.route_path("my_account_password"))

View file

@ -19,11 +19,17 @@ except ImportError:
class LdapDao(AuthLdapBase):
default_tls_cert_dir = "/etc/openldap/cacerts"
scope_labels = {
ldap.SCOPE_BASE: "SCOPE_BASE",
ldap.SCOPE_ONELEVEL: "SCOPE_ONELEVEL",
ldap.SCOPE_SUBTREE: "SCOPE_SUBTREE",
}
@staticmethod
def _scope_labels():
return {
ldap.SCOPE_BASE: "SCOPE_BASE",
ldap.SCOPE_ONELEVEL: "SCOPE_ONELEVEL",
ldap.SCOPE_SUBTREE: "SCOPE_SUBTREE",
}
@property
def scope_labels(self):
return self._scope_labels()
def __init__(
self,

View file

@ -0,0 +1 @@
# rc_license stub — CE edition does not include license management

View file

@ -0,0 +1,21 @@
# rc_license.models stub — CE edition
class LicenseModel:
"""Stub license model for Community Edition."""
@staticmethod
def get_license_data():
return {}
@staticmethod
def get_license_info():
return {"edition": "CE"}
def apply_license(*args, **kwargs):
pass
def apply_license_from_file(*args, **kwargs):
pass

View file

@ -0,0 +1 @@
# vcsserver stub — allows rhodecode to import without the full vcsserver package

View file

@ -0,0 +1 @@
# Stub — vcsserver hooks not available without full vcsserver package

View file

@ -0,0 +1,2 @@
# Re-export from rhodecode's own vcs_common module
from rhodecode.lib.vcs_common import *

View file

@ -819,7 +819,8 @@ class Flash(object):
for msg in session.pop_flash():
messages.append(_Message("notice", msg))
session.save()
if hasattr(session, 'save'):
session.save()
return messages
def json_alerts(self, session=None, request=None):