浏览代码

Stale permissions (#10768)

* dashfolders: hide permissions in settings if folder has changed

and the dashboard has not been saved yet. Otherwise the use will
see stale permissions from the original folder.

* dashfolders: return folder url for inherited permissions
Daniel Lee 7 年之前
父节点
当前提交
2d1bd270fb

+ 6 - 0
pkg/api/dashboard_acl.go

@@ -24,6 +24,12 @@ func GetDashboardAclList(c *middleware.Context) Response {
 		return ApiError(500, "Failed to get dashboard acl", err)
 	}
 
+	for _, perm := range acl {
+		if perm.Slug != "" {
+			perm.Url = m.GetDashboardFolderUrl(perm.IsFolder, perm.Uid, perm.Slug)
+		}
+	}
+
 	return Json(200, acl)
 }
 

+ 5 - 0
pkg/models/dashboard_acl.go

@@ -59,6 +59,11 @@ type DashboardAclInfoDTO struct {
 	Role           *RoleType      `json:"role,omitempty"`
 	Permission     PermissionType `json:"permission"`
 	PermissionName string         `json:"permissionName"`
+	Uid            string         `json:"uid"`
+	Title          string         `json:"title"`
+	Slug           string         `json:"slug"`
+	IsFolder       bool           `json:"isFolder"`
+	Url            string         `json:"url"`
 }
 
 //

+ 26 - 6
pkg/services/sqlstore/dashboard_acl.go

@@ -113,6 +113,7 @@ func SetDashboardAcl(cmd *m.SetDashboardAclCommand) error {
 	})
 }
 
+// RemoveDashboardAcl removes a specified permission from the dashboard acl
 func RemoveDashboardAcl(cmd *m.RemoveDashboardAclCommand) error {
 	return inTransaction(func(sess *DBSession) error {
 		var rawSQL = "DELETE FROM " + dialect.Quote("dashboard_acl") + " WHERE org_id =? and id=?"
@@ -125,6 +126,11 @@ func RemoveDashboardAcl(cmd *m.RemoveDashboardAclCommand) error {
 	})
 }
 
+// GetDashboardAclInfoList returns a list of permissions for a dashboard. They can be fetched from three
+// different places.
+// 1) Permissions for the dashboard
+// 2) permissions for its parent folder
+// 3) if no specific permissions have been set for the dashboard or its parent folder then get the default permissions
 func GetDashboardAclInfoList(query *m.GetDashboardAclInfoListQuery) error {
 	var err error
 
@@ -141,7 +147,11 @@ func GetDashboardAclInfoList(query *m.GetDashboardAclInfoListQuery) error {
 		da.updated,
 		'' as user_login,
 		'' as user_email,
-		'' as team
+		'' as team,
+		'' as title,
+		'' as slug,
+		'' as uid,` +
+			dialect.BooleanStr(false) + ` AS is_folder
 		FROM dashboard_acl as da
 		WHERE da.dashboard_id = -1`
 		query.Result = make([]*m.DashboardAclInfoDTO, 0)
@@ -155,6 +165,7 @@ func GetDashboardAclInfoList(query *m.GetDashboardAclInfoListQuery) error {
 		  )`, query.DashboardId, query.DashboardId)
 
 		rawSQL := `
+			-- get permissions for the dashboard and its parent folder
 			SELECT
 				da.id,
 				da.org_id,
@@ -167,13 +178,18 @@ func GetDashboardAclInfoList(query *m.GetDashboardAclInfoListQuery) error {
 				da.updated,
 				u.login AS user_login,
 				u.email AS user_email,
-				ug.name AS team
+				ug.name AS team,
+				d.title,
+				d.slug,
+				d.uid,
+				d.is_folder
 		  FROM` + dialect.Quote("dashboard_acl") + ` as da
 				LEFT OUTER JOIN ` + dialect.Quote("user") + ` AS u ON u.id = da.user_id
 				LEFT OUTER JOIN team ug on ug.id = da.team_id
+				LEFT OUTER JOIN dashboard d on da.dashboard_id = d.id
 			WHERE dashboard_id ` + dashboardFilter + ` AND da.org_id = ?
 
-			-- Also include default permission if has_acl = 0
+			-- Also include default permissions if folder or dashboard field "has_acl" is false
 
 			UNION
 				SELECT
@@ -188,10 +204,14 @@ func GetDashboardAclInfoList(query *m.GetDashboardAclInfoListQuery) error {
 					da.updated,
 					'' as user_login,
 					'' as user_email,
-					'' as team
-					FROM dashboard_acl as da,
+					'' as team,
+					folder.title,
+					folder.slug,
+					folder.uid,
+					folder.is_folder
+				FROM dashboard_acl as da,
 				dashboard as dash
-				LEFT JOIN dashboard folder on dash.folder_id = folder.id
+				LEFT OUTER JOIN dashboard folder on dash.folder_id = folder.id
 					WHERE
 						dash.id = ? AND (
 							dash.has_acl = ` + dialect.BooleanStr(false) + ` or

+ 1 - 1
public/app/containers/ManageDashboards/FolderPermissions.tsx

@@ -63,7 +63,7 @@ export class FolderPermissions extends Component<IContainerProps, any> {
             </button>
           </div>
           <SlideDown in={permissions.isAddPermissionsVisible}>
-            <AddPermissions permissions={permissions} backendSrv={backendSrv} dashboardId={dashboardId} />
+            <AddPermissions permissions={permissions} backendSrv={backendSrv} />
           </SlideDown>
           <Permissions permissions={permissions} isFolder={true} dashboardId={dashboardId} backendSrv={backendSrv} />
         </div>

+ 1 - 1
public/app/core/components/Permissions/AddPermissions.jest.tsx

@@ -26,7 +26,7 @@ describe('AddPermissions', () => {
       }
     );
 
-    wrapper = shallow(<AddPermissions permissions={store.permissions} backendSrv={backendSrv} dashboardId={1} />);
+    wrapper = shallow(<AddPermissions permissions={store.permissions} backendSrv={backendSrv} />);
     instance = wrapper.instance();
     return store.permissions.load(1, true, false);
   });

+ 0 - 7
public/app/core/components/Permissions/AddPermissions.tsx

@@ -9,7 +9,6 @@ import { permissionOptions } from 'app/stores/PermissionsStore/PermissionsStore'
 export interface IProps {
   permissions: any;
   backendSrv: any;
-  dashboardId: any;
 }
 @observer
 class AddPermissions extends Component<IProps, any> {
@@ -31,12 +30,6 @@ class AddPermissions extends Component<IProps, any> {
     const { value } = evt.target;
     const { permissions } = this.props;
 
-    // if (value === 'Viewer' || value === 'Editor') {
-    // //   permissions.addStoreItem({ permission: 1, role: value, dashboardId: dashboardId }, dashboardId);
-    // //   this.resetNewType();
-    //   return;
-    // }
-
     permissions.setNewType(value);
   }
 

+ 1 - 1
public/app/core/components/Permissions/DashboardPermissions.tsx

@@ -53,7 +53,7 @@ class DashboardPermissions extends Component<IProps, any> {
           </div>
         </div>
         <SlideDown in={this.permissions.isAddPermissionsVisible}>
-          <AddPermissions permissions={this.permissions} backendSrv={backendSrv} dashboardId={dashboardId} />
+          <AddPermissions permissions={this.permissions} backendSrv={backendSrv} />
         </SlideDown>
         <Permissions
           permissions={this.permissions}

+ 4 - 1
public/app/features/dashboard/settings/settings.html

@@ -96,11 +96,14 @@
 </div>
 
 <div class="dashboard-settings__content" ng-if="ctrl.viewId === 'permissions'" >
-  <dashboard-permissions ng-if="ctrl.dashboard"
+  <dashboard-permissions ng-if="ctrl.dashboard && !ctrl.hasUnsavedFolderChange"
     dashboardId="ctrl.dashboard.id"
     backendSrv="ctrl.backendSrv"
     folder="ctrl.getFolder()"
   />
+  <div ng-if="ctrl.hasUnsavedFolderChange">
+    <h5>You have changed folder, please save to view permissions.</h5>
+  </div>
 </div>
 
 <div class="dashboard-settings__content" ng-if="ctrl.viewId === '404'">

+ 7 - 1
public/app/features/dashboard/settings/settings.ts

@@ -14,6 +14,7 @@ export class SettingsCtrl {
   canSave: boolean;
   canDelete: boolean;
   sections: any[];
+  hasUnsavedFolderChange: boolean;
 
   /** @ngInject */
   constructor(private $scope, private $location, private $rootScope, private backendSrv, private dashboardSrv) {
@@ -38,6 +39,7 @@ export class SettingsCtrl {
 
     this.$rootScope.onAppEvent('$routeUpdate', this.onRouteUpdated.bind(this), $scope);
     this.$rootScope.appEvent('dash-scroll', { animate: false, pos: 0 });
+    this.$rootScope.onAppEvent('dashboard-saved', this.onPostSave.bind(this), $scope);
   }
 
   buildSectionList() {
@@ -135,6 +137,10 @@ export class SettingsCtrl {
     this.dashboardSrv.saveDashboard();
   }
 
+  onPostSave() {
+    this.hasUnsavedFolderChange = false;
+  }
+
   hideSettings() {
     var urlParams = this.$location.search();
     delete urlParams.editview;
@@ -195,7 +201,7 @@ export class SettingsCtrl {
   onFolderChange(folder) {
     this.dashboard.meta.folderId = folder.id;
     this.dashboard.meta.folderTitle = folder.title;
-    this.dashboard.meta.folderSlug = folder.slug;
+    this.hasUnsavedFolderChange = true;
   }
 
   getFolder() {