Compatibility layer for plugins depending on user.is_anonymous() etc
Logs a deprecation warning when any of the made-property fields is accessed as a getter and return value. Implements __eq__, __ne__, __bool__ and __nonzero__ to allow things like "user.is_anonymous == True" or "not user.is_anonymous" is used. Careful with serialization to json, needs "bool(...)" wrapper to not cause an exception (or inclusion in a custom serializer). Affected fields: * is_anonymous * is_authenticated * is_active * is_user * is_admin To be removed again in OctoPrint 1.5.0
This commit is contained in:
parent
0adb62b485
commit
b7a0f5bee5
2 changed files with 91 additions and 7 deletions
|
|
@ -336,6 +336,7 @@ class Server(object):
|
|||
loginManager = LoginManager()
|
||||
loginManager.session_protection = "strong"
|
||||
loginManager.user_callback = load_user
|
||||
loginManager.anonymous_user = users.AnonymousUser # TODO: remove in 1.5.0
|
||||
if not userManager.enabled:
|
||||
loginManager.anonymous_user = users.DummyUser
|
||||
principals.identity_loaders.appendleft(users.dummy_identity_loader)
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ __author__ = "Gina Häußge <osd@foosel.net>"
|
|||
__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html'
|
||||
__copyright__ = "Copyright (C) 2014 The OctoPrint Project - Released under terms of the AGPLv3 License"
|
||||
|
||||
from flask_login import UserMixin
|
||||
from flask_login import UserMixin, AnonymousUserMixin
|
||||
from flask_principal import Identity
|
||||
from werkzeug.local import LocalProxy
|
||||
import hashlib
|
||||
|
|
@ -413,6 +413,65 @@ class UnknownRole(Exception):
|
|||
|
||||
##~~ User object
|
||||
|
||||
class MethodReplacedByBooleanProperty(object):
|
||||
|
||||
def __init__(self, name, message, getter):
|
||||
self._name = name
|
||||
self._message = message
|
||||
self._getter = getter
|
||||
|
||||
@property
|
||||
def _attr(self):
|
||||
return self._getter()
|
||||
|
||||
def __call__(self):
|
||||
from warnings import warn
|
||||
warn(DeprecationWarning(self._message.format(name=self._name)), stacklevel=2)
|
||||
return self._attr
|
||||
|
||||
def __eq__(self, other):
|
||||
return self._attr == other
|
||||
|
||||
def __ne__(self, other):
|
||||
return self._attr != other
|
||||
|
||||
def __bool__(self):
|
||||
# Python 3
|
||||
return self._attr
|
||||
|
||||
def __nonzero__(self):
|
||||
# Python 2
|
||||
return self._attr
|
||||
|
||||
def __hash__(self):
|
||||
return hash(self._attr)
|
||||
|
||||
def __repr__(self):
|
||||
return "MethodReplacedByProperty({}, {}, {})".format(self._name, self._message, self._getter)
|
||||
|
||||
def __str__(self):
|
||||
return str(self._attr)
|
||||
|
||||
|
||||
# TODO: Remove compatibility layer in OctoPrint 1.5.0
|
||||
class FlaskLoginMethodReplacedByBooleanProperty(MethodReplacedByBooleanProperty):
|
||||
|
||||
def __init__(self, name, getter):
|
||||
message = "{name} is now a property in Flask-Login versions >= 0.3.0, which OctoPrint now uses. " + \
|
||||
"Use {name} instead of {name}(). This compatibility layer will be removed in OctoPrint 1.5.0."
|
||||
MethodReplacedByBooleanProperty.__init__(self, name, message, getter)
|
||||
|
||||
|
||||
# TODO: Remove compatibility layer in OctoPrint 1.5.0
|
||||
class OctoPrintUserMethodReplacedByBooleanProperty(MethodReplacedByBooleanProperty):
|
||||
|
||||
def __init__(self, name, getter):
|
||||
message = "{name} is now a property for consistency reasons with Flask-Login versions >= 0.3.0, which " + \
|
||||
"OctoPrint now uses. Use {name} instead of {name}(). This compatibility layer will be removed " + \
|
||||
"in OctoPrint 1.5.0."
|
||||
MethodReplacedByBooleanProperty.__init__(self, name, message, getter)
|
||||
|
||||
|
||||
class User(UserMixin):
|
||||
def __init__(self, username, passwordHash, active, roles, apikey=None, settings=None):
|
||||
self._username = username
|
||||
|
|
@ -428,9 +487,9 @@ class User(UserMixin):
|
|||
def asDict(self):
|
||||
return {
|
||||
"name": self._username,
|
||||
"active": self.is_active,
|
||||
"admin": self.is_admin,
|
||||
"user": self.is_user,
|
||||
"active": bool(self.is_active),
|
||||
"admin": bool(self.is_admin),
|
||||
"user": bool(self.is_user),
|
||||
"apikey": self._apikey,
|
||||
"settings": self._settings
|
||||
}
|
||||
|
|
@ -444,17 +503,25 @@ class User(UserMixin):
|
|||
def get_name(self):
|
||||
return self._username
|
||||
|
||||
@property
|
||||
def is_anonymous(self):
|
||||
return FlaskLoginMethodReplacedByBooleanProperty("is_anonymous", lambda: False)
|
||||
|
||||
@property
|
||||
def is_authenticated(self):
|
||||
return FlaskLoginMethodReplacedByBooleanProperty("is_authenticated", lambda: True)
|
||||
|
||||
@property
|
||||
def is_active(self):
|
||||
return self._active
|
||||
return FlaskLoginMethodReplacedByBooleanProperty("is_active", lambda: self._active)
|
||||
|
||||
@property
|
||||
def is_user(self):
|
||||
return "user" in self._roles
|
||||
return OctoPrintUserMethodReplacedByBooleanProperty("is_user", lambda: "user" in self._roles)
|
||||
|
||||
@property
|
||||
def is_admin(self):
|
||||
return "admin" in self._roles
|
||||
return OctoPrintUserMethodReplacedByBooleanProperty("is_admin", lambda: "admin" in self._roles)
|
||||
|
||||
def get_all_settings(self):
|
||||
return self._settings
|
||||
|
|
@ -505,6 +572,22 @@ class User(UserMixin):
|
|||
def __repr__(self):
|
||||
return "User(id=%s,name=%s,active=%r,user=%r,admin=%r)" % (self.get_id(), self.get_name(), self.is_active, self.is_user, self.is_admin)
|
||||
|
||||
|
||||
class AnonymousUser(AnonymousUserMixin):
|
||||
|
||||
@property
|
||||
def is_anonymous(self):
|
||||
return FlaskLoginMethodReplacedByBooleanProperty("is_anonymous", lambda: True)
|
||||
|
||||
@property
|
||||
def is_authenticated(self):
|
||||
return FlaskLoginMethodReplacedByBooleanProperty("is_authenticated", lambda: False)
|
||||
|
||||
@property
|
||||
def is_active(self):
|
||||
return FlaskLoginMethodReplacedByBooleanProperty("is_active", lambda: False)
|
||||
|
||||
|
||||
class SessionUser(User):
|
||||
def __init__(self, user):
|
||||
self._user = user
|
||||
|
|
|
|||
Loading…
Reference in a new issue