1package dashboards
2
3import (
4	"bytes"
5	"context"
6	"encoding/json"
7	"fmt"
8	"io/ioutil"
9	"net/http"
10	"testing"
11
12	"github.com/grafana/grafana/pkg/api/dtos"
13	"github.com/grafana/grafana/pkg/components/simplejson"
14	"github.com/grafana/grafana/pkg/models"
15	"github.com/grafana/grafana/pkg/plugins"
16	"github.com/grafana/grafana/pkg/services/sqlstore"
17	"github.com/grafana/grafana/pkg/tests/testinfra"
18	"github.com/stretchr/testify/assert"
19	"github.com/stretchr/testify/require"
20)
21
22func TestDashboardQuota(t *testing.T) {
23	// enable quota and set low dashboard quota
24	// Setup Grafana and its Database
25	dashboardQuota := int64(1)
26	dir, path := testinfra.CreateGrafDir(t, testinfra.GrafanaOpts{
27		DisableAnonymous:  true,
28		EnableQuota:       true,
29		DashboardOrgQuota: &dashboardQuota,
30	})
31	grafanaListedAddr, store := testinfra.StartGrafana(t, dir, path)
32	// Create user
33	createUser(t, store, models.CreateUserCommand{
34		DefaultOrgRole: string(models.ROLE_ADMIN),
35		Password:       "admin",
36		Login:          "admin",
37	})
38
39	t.Run("when quota limit doesn't exceed, importing a dashboard should succeed", func(t *testing.T) {
40		// Import dashboard
41		dashboardDataOne, err := simplejson.NewJson([]byte(`{"title":"just testing"}`))
42		require.NoError(t, err)
43		buf1 := &bytes.Buffer{}
44		err = json.NewEncoder(buf1).Encode(dtos.ImportDashboardCommand{
45			Dashboard: dashboardDataOne,
46		})
47		require.NoError(t, err)
48		u := fmt.Sprintf("http://admin:admin@%s/api/dashboards/import", grafanaListedAddr)
49		// nolint:gosec
50		resp, err := http.Post(u, "application/json", buf1)
51		require.NoError(t, err)
52		assert.Equal(t, http.StatusOK, resp.StatusCode)
53		t.Cleanup(func() {
54			err := resp.Body.Close()
55			require.NoError(t, err)
56		})
57		b, err := ioutil.ReadAll(resp.Body)
58		require.NoError(t, err)
59		dashboardDTO := &plugins.PluginDashboardInfoDTO{}
60		err = json.Unmarshal(b, dashboardDTO)
61		require.NoError(t, err)
62		require.EqualValues(t, 1, dashboardDTO.DashboardId)
63	})
64
65	t.Run("when quota limit exceeds importing a dashboard should fail", func(t *testing.T) {
66		dashboardDataOne, err := simplejson.NewJson([]byte(`{"title":"just testing"}`))
67		require.NoError(t, err)
68		buf1 := &bytes.Buffer{}
69		err = json.NewEncoder(buf1).Encode(dtos.ImportDashboardCommand{
70			Dashboard: dashboardDataOne,
71		})
72		require.NoError(t, err)
73		u := fmt.Sprintf("http://admin:admin@%s/api/dashboards/import", grafanaListedAddr)
74		// nolint:gosec
75		resp, err := http.Post(u, "application/json", buf1)
76		require.NoError(t, err)
77		assert.Equal(t, http.StatusForbidden, resp.StatusCode)
78		t.Cleanup(func() {
79			err := resp.Body.Close()
80			require.NoError(t, err)
81		})
82		b, err := ioutil.ReadAll(resp.Body)
83		require.NoError(t, err)
84		assert.Equal(t, http.StatusForbidden, resp.StatusCode)
85		require.JSONEq(t, `{"message":"Quota reached"}`, string(b))
86	})
87}
88
89func createUser(t *testing.T, store *sqlstore.SQLStore, cmd models.CreateUserCommand) int64 {
90	t.Helper()
91	u, err := store.CreateUser(context.Background(), cmd)
92	require.NoError(t, err)
93	return u.Id
94}
95