package database import ( "context" "strconv" "strings" "github.com/grafana/grafana/pkg/infra/db" "github.com/grafana/grafana/pkg/services/accesscontrol" ) func ProvideService(sql db.DB) *AccessControlStore { return &AccessControlStore{sql} } type AccessControlStore struct { sql db.DB } func (s *AccessControlStore) GetUserPermissions(ctx context.Context, query accesscontrol.GetUserPermissionsQuery) ([]accesscontrol.Permission, error) { result := make([]accesscontrol.Permission, 0) err := s.sql.WithDbSession(ctx, func(sess *db.Session) error { if query.UserID == 0 && len(query.TeamIDs) == 0 && len(query.Roles) == 0 { // no permission to fetch return nil } filter, params := accesscontrol.UserRolesFilter(query.OrgID, query.UserID, query.TeamIDs, query.Roles) q := ` SELECT permission.action, permission.scope FROM permission INNER JOIN role ON role.id = permission.role_id ` + filter if len(query.Actions) > 0 { q += " WHERE permission.action IN(" if len(query.Actions) > 0 { q += "?" + strings.Repeat(",?", len(query.Actions)-1) } q += ")" for _, a := range query.Actions { params = append(params, a) } } if err := sess.SQL(q, params...).Find(&result); err != nil { return err } return nil }) return result, err } func (s *AccessControlStore) DeleteUserPermissions(ctx context.Context, orgID, userID int64) error { err := s.sql.WithDbSession(ctx, func(sess *db.Session) error { roleDeleteQuery := "DELETE FROM user_role WHERE user_id = ?" roleDeleteParams := []interface{}{roleDeleteQuery, userID} if orgID != accesscontrol.GlobalOrgID { roleDeleteQuery += " AND org_id = ?" roleDeleteParams = []interface{}{roleDeleteQuery, userID, orgID} } // Delete user role assignments if _, err := sess.Exec(roleDeleteParams...); err != nil { return err } // only delete scopes to user if all permissions is removed (i.e. user is removed) if orgID == accesscontrol.GlobalOrgID { // Delete permissions that are scoped to user if _, err := sess.Exec("DELETE FROM permission WHERE scope = ?", accesscontrol.Scope("users", "id", strconv.FormatInt(userID, 10))); err != nil { return err } } roleQuery := "SELECT id FROM role WHERE name = ?" roleParams := []interface{}{accesscontrol.ManagedUserRoleName(userID)} if orgID != accesscontrol.GlobalOrgID { roleQuery += " AND org_id = ?" roleParams = []interface{}{accesscontrol.ManagedUserRoleName(userID), orgID} } var roleIDs []int64 if err := sess.SQL(roleQuery, roleParams...).Find(&roleIDs); err != nil { return err } if len(roleIDs) == 0 { return nil } permissionDeleteQuery := "DELETE FROM permission WHERE role_id IN(? " + strings.Repeat(",?", len(roleIDs)-1) + ")" permissionDeleteParams := make([]interface{}, 0, len(roleIDs)+1) permissionDeleteParams = append(permissionDeleteParams, permissionDeleteQuery) for _, id := range roleIDs { permissionDeleteParams = append(permissionDeleteParams, id) } // Delete managed user permissions if _, err := sess.Exec(permissionDeleteParams...); err != nil { return err } managedRoleDeleteQuery := "DELETE FROM role WHERE id IN(? " + strings.Repeat(",?", len(roleIDs)-1) + ")" managedRoleDeleteParams := []interface{}{managedRoleDeleteQuery} for _, id := range roleIDs { managedRoleDeleteParams = append(managedRoleDeleteParams, id) } // Delete managed user roles if _, err := sess.Exec(managedRoleDeleteParams...); err != nil { return err } return nil }) return err }