Skip to content
Browse files

Added support for 2 extra authorization modes for dashboard:

- Use Django change and delete permissions, as assigned in the Admin app
- Allow edit/delete for any user in a specified group.
  • Loading branch information...
1 parent 68722dd commit 682c07e789fd336fed713dc8f8e8037a6e9be1f0 @captsens captsens committed Mar 2, 2013
View
34 webapp/content/js/dashboard.js
@@ -119,8 +119,13 @@ function isLoggedIn() {
return userName != null;
}
-function canMakeChanges() {
- return isLoggedIn() || !requireAuthentication;
+function hasPermission(permission) {
+ for (i in permissions) {
+ if (permissions[i] === permission) {
+ return true;
+ }
+ }
+ return false;
}
function initDashboard () {
@@ -540,12 +545,12 @@ function initDashboard () {
handler: function (item, e) {
sendSaveRequest(dashboardName);
},
- disabled: dashboardName == null || !canMakeChanges()
+ disabled: dashboardName == null || !hasPermission('change')
}, {
id: "dashboard-save-as-button",
text: "Save As",
handler: saveDashboard,
- disabled: !canMakeChanges()
+ disabled: !hasPermission('change')
}, {
text: "Configure UI",
handler: configureUI
@@ -1389,7 +1394,7 @@ function newFromSavedGraph() {
function handleSelects(selModel, nodes) {
Ext.each(nodes, function (node, index) {
if (!node.leaf) {
- node.unselect();
+ node.unselect();
node.toggle();
}
});
@@ -2448,7 +2453,7 @@ function setDashboardName(name) {
dashboardName = name;
var saveButton = Ext.getCmp('dashboard-save-button');
- if (name == null || !canMakeChanges()) {
+ if (name == null || !hasPermission('change')) {
dashboardURL = null;
document.title = "untitled - Graphite Dashboard";
navBar.setTitle("untitled");
@@ -2607,7 +2612,7 @@ function showDashboardFinder() {
Ext.getCmp('finder-delete-button').disable();
} else {
Ext.getCmp('finder-open-button').enable();
- if (canMakeChanges()) {
+ if (hasPermission('delete')) {
Ext.getCmp('finder-delete-button').enable();
} else {
Ext.getCmp('finder-delete-button').disable();
@@ -2895,8 +2900,8 @@ function getLoginMenuItemText() {
/* After login/logout, make any necessary adjustments to Dashboard menu items (text and/or disabled) */
function postLoginMenuAdjust() {
Ext.getCmp("dashboard-login-button").setText(getLoginMenuItemText());
- Ext.getCmp("dashboard-save-button").setDisabled(dashboardName == null || !canMakeChanges());
- Ext.getCmp("dashboard-save-as-button").setDisabled(!canMakeChanges());
+ Ext.getCmp("dashboard-save-button").setDisabled(dashboardName == null || !hasPermission('change'));
+ Ext.getCmp("dashboard-save-as-button").setDisabled(!hasPermission('change'));
}
function showLoginForm() {
@@ -2907,7 +2912,6 @@ function showLoginForm() {
defaultType: 'textfield',
monitorValid: true,
- // The "name" attribute defines the name of variables sent to the server.
items: [{
fieldLabel: 'Username',
name: 'username',
@@ -2922,20 +2926,20 @@ function showLoginForm() {
allowBlank: false
}
],
-
buttons: [
{text: 'Login', formBind: true, handler: doLogin},
{text: 'Cancel', handler: function () { win.close(); } }
]
});
-
+
function doLogin() {
login.getForm().submit({
method: 'POST',
url: '/dashboard/login',
waitMsg: 'Authenticating...',
- success: function() {
- userName = login.getForm().findField('username').getValue();
+ success: function(form, action) {
+ userName = form.findField('username').getValue();
+ permissions = action.result.permissions;
postLoginMenuAdjust();
win.close();
},
@@ -2970,11 +2974,13 @@ function logout() {
method: 'POST',
success: function() {
userName = null;
+ permissions = permissionsUnauthenticated;
postLoginMenuAdjust();
},
failure: function() {
// Probably because they no longer have a valid session - assume they're now logged out
userName = null;
+ permissions = permissionsUnauthenticated;
postLoginMenuAdjust();
}
});
View
42 webapp/graphite/dashboard/views.py
@@ -38,6 +38,7 @@
'give_completer_focus' : 'shift-space',
}
+ALL_PERMISSIONS = ['change', 'delete']
class DashboardConfig:
def __init__(self):
@@ -132,7 +133,8 @@ def dashboard(request, name=None):
'querystring' : json.dumps( dict( request.GET.items() ) ),
'dashboard_conf_missing' : dashboard_conf_missing,
'userName': '',
- 'requireAuthentication': settings.DASHBOARD_REQUIRE_AUTHENTICATION
+ 'permissions': json.dumps(getPermissions(request.user)),
+ 'permissionsUnauthenticated': json.dumps(getPermissions(None))
}
user = request.user
if user:
@@ -149,15 +151,32 @@ def dashboard(request, name=None):
return render_to_response("dashboard.html", context)
-def canMakeChanges(request):
- return (request.user is not None and request.user.is_authenticated()) \
- or not settings.DASHBOARD_REQUIRE_AUTHENTICATION
-
+def getPermissions(user):
+ """Return [change, delete] based on authorisation model and user privileges/groups"""
+ if user and not user.is_authenticated():
+ user = None
+ if not user:
+ if not settings.DASHBOARD_REQUIRE_AUTHENTICATION and not settings.DASHBOARD_REQUIRE_PERMISSIONS \
+ and not settings.DASHBOARD_EDIT_GROUP:
+ return ALL_PERMISSIONS # don't require login
+ else:
+ return []
+ # from here on, we have a user
+ if settings.DASHBOARD_REQUIRE_PERMISSIONS:
+ return [permission for permission in ALL_PERMISSIONS \
+ if user.has_perm('dashboard.%s_dashboard' % permission)]
+ editGroup = settings.DASHBOARD_EDIT_GROUP
+ if editGroup:
+ if len(user.groups.filter(name = editGroup)) > 0:
+ return ALL_PERMISSIONS
+ else:
+ return []
+ return ALL_PERMISSIONS
+
def save(request, name):
- if not canMakeChanges(request):
- return json_response( dict(error="Must be logged in to save") )
-
+ if 'change' not in getPermissions(request.user):
+ return json_response( dict(error="Must be logged in with appropriate permissions to save") )
# Deserialize and reserialize as a validation step
state = str( json.dumps( json.loads( request.POST['state'] ) ) )
@@ -182,8 +201,8 @@ def load(request, name):
def delete(request, name):
- if not canMakeChanges(request):
- return json_response( dict(error="Must be logged in to delete") )
+ if 'delete' not in getPermissions(request.user):
+ return json_response( dict(error="Must be logged in with appropriate permissions to delete") )
try:
dashboard = Dashboard.objects.get(name=name)
@@ -270,13 +289,14 @@ def json_response(obj):
def user_login(request):
- response = dict(errors={}, text={}, success=False)
+ response = dict(errors={}, text={}, success=False, permissions=[])
user = authenticate(username=request.POST['username'],
password=request.POST['password'])
if user is not None:
if user.is_active:
login(request, user)
response['success'] = True
+ response['permissions'].extend(getPermissions(user))
else:
response['errors']['reason'] = 'Account disabled.'
else:
View
20 webapp/graphite/local_settings.py.example
@@ -119,9 +119,27 @@
# Override the URL for the login link (e.g. for django_openid_auth)
#LOGIN_URL = '/account/login'
-# Require users to be logged in to save or delete dashboards (defaults to False)
+
+###############################
+# Authorization for Dashboard #
+###############################
+# By default, there is no security on dashboards - any user can add, change or delete them.
+#
+# This section provides 3 different authorization models, of increasing strictness. If you
+# want security on your dashboards, you should choose JUST ONE of these settings.
+
+# If set to True, dashboards can be saved and deleted by any logged-in user. Defaults to False
#DASHBOARD_REQUIRE_AUTHENTICATION = True
+# If set to the name of a user group, dashboards can be saved and deleted by any user in this
+# group. Groups can be set in the Django Admin app, or in LDAP. Defaults to None
+#DASHBOARD_EDIT_GROUP = 'dashboard-editors-group'
+
+# If set to True, dashboards can be saved or deleted by any user having the appropriate
+# (change or delete) permission (as set in the Django Admin app). Defaults to False
+#DASHBOARD_REQUIRE_PERMISSIONS = True
+
+
##########################
# Database Configuration #
View
5 webapp/graphite/settings.py
@@ -95,6 +95,11 @@
# Set to True to require authentication to save or delete dashboards
DASHBOARD_REQUIRE_AUTHENTICATION = False
+# Require Django change/delete permissions to save or delete dashboards
+DASHBOARD_REQUIRE_PERMISSIONS = False
+# Name of a group to which the user must belong to save or delete dashboards. Alternative to
+# DASHBOARD_REQUIRE_PERMISSIONS, particularly useful when using only LDAP (without Admin app)
+DASHBOARD_EDIT_GROUP = None
#Initialize database settings - Old style (pre 1.2)
DATABASE_ENGINE = 'django.db.backends.sqlite3' # 'postgresql', 'mysql', 'sqlite3' or 'ado_mssql'.
View
7 webapp/graphite/templates/dashboard.html
@@ -38,11 +38,8 @@
var queryString = {{querystring|safe}};
{% endif %}
- {% if requireAuthentication %}
- var requireAuthentication = true;
- {% else %}
- var requireAuthentication = false;
- {% endif %}
+ var permissions = {{permissions|safe}};
+ var permissionsUnauthenticated = {{permissionsUnauthenticated|safe}};
{% if userName %}
var userName = '{{userName|safe}}';

0 comments on commit 682c07e

Please sign in to comment.
Something went wrong with that request. Please try again.