Disabled ACL is now tracked through enabled flag on UserManager

That allows us to properly enable and disable it at runtime (during first run).
This commit is contained in:
Gina Häußge 2015-12-17 13:08:45 +01:00
parent ccd2ddc056
commit b96d1b51e0
11 changed files with 55 additions and 32 deletions

View file

@ -101,7 +101,7 @@ def load_user(id):
else:
sessionid = None
if settings().getBoolean(["accessControl", "enabled"]) and userManager is not None:
if userManager.enabled:
if sessionid:
return userManager.findUser(userid=id, session=sessionid)
else:
@ -291,13 +291,15 @@ class Server():
events.DebugEventListener()
# setup access control
if s.getBoolean(["accessControl", "enabled"]):
userManagerName = s.get(["accessControl", "userManager"])
try:
clazz = octoprint.util.get_class(userManagerName)
userManager = clazz()
except AttributeError, e:
self._logger.exception("Could not instantiate user manager %s, will run with accessControl disabled!" % userManagerName)
userManagerName = s.get(["accessControl", "userManager"])
try:
clazz = octoprint.util.get_class(userManagerName)
userManager = clazz()
except AttributeError, e:
self._logger.exception("Could not instantiate user manager {}, falling back to FilebasedUserManager!".format(userManagerName))
userManager = octoprint.users.FilebasedUserManager()
finally:
userManager.enabled = s.getBoolean(["accessControl", "enabled"])
app.wsgi_app = util.ReverseProxied(
app.wsgi_app,
@ -321,7 +323,7 @@ class Server():
loginManager = LoginManager()
loginManager.session_protection = "strong"
loginManager.user_callback = load_user
if userManager is None:
if not userManager.enabled:
loginManager.anonymous_user = users.DummyUser
principals.identity_loaders.appendleft(users.dummy_identity_loader)
loginManager.init_app(app)
@ -535,7 +537,7 @@ class Server():
if "l10n" in request.values:
return Locale.negotiate([request.values["l10n"]], LANGUAGES)
if hasattr(g, "identity") and g.identity and userManager is not None:
if hasattr(g, "identity") and g.identity and userManager.enabled:
userid = g.identity.id
try:
user_language = userManager.getUserSetting(userid, ("interface", "language"))

View file

@ -111,6 +111,7 @@ def firstRunSetup():
"pass2" in request.values.keys() and request.values["pass1"] == request.values["pass2"]:
# configure access control
s().setBoolean(["accessControl", "enabled"], True)
octoprint.server.userManager.enable()
octoprint.server.userManager.addUser(request.values["user"], request.values["pass1"], True, ["user", "admin"])
s().setBoolean(["server", "firstRun"], False)
elif "ac" in request.values.keys() and not request.values["ac"] in valid_boolean_trues:
@ -120,6 +121,7 @@ def firstRunSetup():
octoprint.server.loginManager.anonymous_user = octoprint.users.DummyUser
octoprint.server.principals.identity_loaders.appendleft(octoprint.users.dummy_identity_loader)
octoprint.server.userManager.disable()
s().save()
return NO_CONTENT
@ -181,7 +183,7 @@ def performSystemAction():
@api.route("/login", methods=["POST"])
def login():
if octoprint.server.userManager is not None and "user" in request.values.keys() and "pass" in request.values.keys():
if octoprint.server.userManager.enabled and "user" in request.values.keys() and "pass" in request.values.keys():
username = request.values["user"]
password = request.values["pass"]
@ -196,7 +198,7 @@ def login():
user = octoprint.server.userManager.findUser(username)
if user is not None:
if octoprint.server.userManager.checkPassword(username, password):
if octoprint.server.userManager is not None:
if octoprint.server.userManager.enabled:
user = octoprint.server.userManager.login_user(user)
session["usersession.id"] = user.get_session()
g.user = user

View file

@ -23,7 +23,7 @@ from octoprint.server.util.flask import restricted_access
@restricted_access
@admin_permission.require(403)
def getUsers():
if userManager is None:
if not userManager.enabled:
return jsonify(SUCCESS)
return jsonify({"users": userManager.getAllUsers()})
@ -33,7 +33,7 @@ def getUsers():
@restricted_access
@admin_permission.require(403)
def addUser():
if userManager is None:
if not userManager.enabled:
return jsonify(SUCCESS)
if not "application/json" in request.headers["Content-Type"]:
@ -62,7 +62,7 @@ def addUser():
@api.route("/users/<username>", methods=["GET"])
@restricted_access
def getUser(username):
if userManager is None:
if not userManager.enabled:
return jsonify(SUCCESS)
if current_user is not None and not current_user.is_anonymous() and (current_user.get_name() == username or current_user.is_admin()):
@ -79,7 +79,7 @@ def getUser(username):
@restricted_access
@admin_permission.require(403)
def updateUser(username):
if userManager is None:
if not userManager.enabled:
return jsonify(SUCCESS)
user = userManager.findUser(username)
@ -110,7 +110,7 @@ def updateUser(username):
@restricted_access
@admin_permission.require(http_exception=403)
def removeUser(username):
if userManager is None:
if not userManager.enabled:
return jsonify(SUCCESS)
try:
@ -123,7 +123,7 @@ def removeUser(username):
@api.route("/users/<username>/password", methods=["PUT"])
@restricted_access
def changePasswordForUser(username):
if userManager is None:
if not userManager.enabled:
return jsonify(SUCCESS)
if current_user is not None and not current_user.is_anonymous() and (current_user.get_name() == username or current_user.is_admin()):
@ -151,7 +151,7 @@ def changePasswordForUser(username):
@api.route("/users/<username>/settings", methods=["GET"])
@restricted_access
def getSettingsForUser(username):
if userManager is None:
if not userManager.enabled:
return jsonify(SUCCESS)
if current_user is None or current_user.is_anonymous() or (current_user.get_name() != username and not current_user.is_admin()):
@ -165,7 +165,7 @@ def getSettingsForUser(username):
@api.route("/users/<username>/settings", methods=["PATCH"])
@restricted_access
def changeSettingsForUser(username):
if userManager is None:
if not userManager.enabled:
return jsonify(SUCCESS)
if current_user is None or current_user.is_anonymous() or (current_user.get_name() != username and not current_user.is_admin()):
@ -185,7 +185,7 @@ def changeSettingsForUser(username):
@api.route("/users/<username>/apikey", methods=["DELETE"])
@restricted_access
def deleteApikeyForUser(username):
if userManager is None:
if not userManager.enabled:
return jsonify(SUCCESS)
if current_user is not None and not current_user.is_anonymous() and (current_user.get_name() == username or current_user.is_admin()):
@ -201,7 +201,7 @@ def deleteApikeyForUser(username):
@api.route("/users/<username>/apikey", methods=["POST"])
@restricted_access
def generateApikeyForUser(username):
if userManager is None:
if not userManager.enabled:
return jsonify(SUCCESS)
if current_user is not None and not current_user.is_anonymous() and (current_user.get_name() == username or current_user.is_admin()):

View file

@ -120,7 +120,7 @@ def get_user_for_apikey(apikey):
if apikey == settings().get(["api", "key"]) or octoprint.server.appSessionManager.validate(apikey):
# master key or an app session key was used
return ApiUser()
elif octoprint.server.userManager is not None:
elif octoprint.server.userManager.enabled:
# user key might have been used
return octoprint.server.userManager.findUser(apikey=apikey)
return None

View file

@ -222,7 +222,7 @@ def fix_webassets_filtertool():
#~~ passive login helper
def passive_login():
if octoprint.server.userManager is not None:
if octoprint.server.userManager.enabled:
user = octoprint.server.userManager.login_user(flask.ext.login.current_user)
else:
user = flask.ext.login.current_user

View file

@ -44,7 +44,7 @@ def index():
enable_gcodeviewer = settings().getBoolean(["gcodeViewer", "enabled"])
enable_timelapse = (settings().get(["webcam", "snapshot"]) and settings().get(["webcam", "ffmpeg"]))
enable_systemmenu = settings().get(["system"]) is not None and settings().get(["system", "actions"]) is not None
enable_accesscontrol = userManager is not None
enable_accesscontrol = userManager.enabled
preferred_stylesheet = settings().get(["devel", "stylesheet"])
locales = dict((l.language, dict(language=l.language, display=l.display_name, english=l.english_name)) for l in LOCALES)
@ -281,11 +281,11 @@ def index():
#~~ prepare full set of template vars for rendering
first_run = settings().getBoolean(["server", "firstRun"]) and (userManager is None or not userManager.hasBeenCustomized())
first_run = settings().getBoolean(["server", "firstRun"]) and userManager.enabled and not userManager.hasBeenCustomized()
render_kwargs = dict(
webcamStream=settings().get(["webcam", "stream"]),
enableTemperatureGraph=settings().get(["feature", "temperatureGraph"]),
enableAccessControl=userManager is not None,
enableAccessControl=userManager.enabled,
enableSdSupport=settings().get(["feature", "sdSupport"]),
firstRun=first_run,
debug=debug,

View file

@ -11,9 +11,6 @@ function DataUpdater(allViewModels) {
self._pluginHash = undefined;
self.reloadOverlay = $("#reloadui_overlay");
$("#reloadui_overlay_reload").click(function() { location.reload(); });
self.connect = function() {
var options = {};
if (SOCKJS_DEBUG) {
@ -142,7 +139,7 @@ function DataUpdater(allViewModels) {
}
if (oldVersion != VERSION || (oldPluginHash != undefined && oldPluginHash != self._pluginHash)) {
self.reloadOverlay.show();
showReloadOverlay();
}
break;

View file

@ -476,6 +476,10 @@ function showConfirmationDialog(message, onacknowledge) {
confirmationDialog.modal("show");
}
function showReloadOverlay() {
$("#reloadui_overlay").show();
}
function commentableLinesToArray(lines) {
return splitTextToArray(lines, "\n", true, function(item) {return !_.startsWith(item, "#")});
}

View file

@ -490,6 +490,9 @@ $(function() {
e.preventDefault();
});
// reload overlay
$("#reloadui_overlay_reload").click(function() { location.reload(); });
//~~ Starting up the app
_.each(allViewModels, function(viewModel) {

View file

@ -46,7 +46,7 @@ $(function() {
};
self._sendData(data, function() {
// if the user indeed disables access control, we'll need to reload the page for this to take effect
//location.reload(true); // TODO: clear cache doesn't work properly, needs a better way, same issue with reloading plugins
showReloadOverlay();
});
});
$("#confirmation_dialog").modal("show");

View file

@ -26,6 +26,21 @@ class UserManager(object):
self._logger = logging.getLogger(__name__)
self._session_users_by_session = dict()
self._session_users_by_userid = dict()
self._enabled = True
@property
def enabled(self):
return self._enabled
@enabled.setter
def enabled(self, value):
self._enabled = value
def enable(self):
self._enabled = True
def disable(self):
self._enabled = False
def login_user(self, user):
self._cleanup_sessions()