mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
API: Restrict anonymous user information access (#18422)
Existing /api/alert-notifications now requires at least editor access. Existing /api/alert-notifiers now requires at least editor access. New /api/alert-notifications/lookup returns less information than /api/alert-notifications and can be access by any authenticated user. Existing /api/org/users now requires org admin role. New /api/org/users/lookup returns less information than /api/org/users and can be access by users that are org admins, admin in any folder or admin of any team. UserPicker component now uses /api/org/users/lookup instead of /api/org/users. Fixes #17318
This commit is contained in:
committed by
GitHub
parent
ab17015794
commit
8fd153edb7
@@ -63,6 +63,48 @@ Content-Type: application/json
|
||||
Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk
|
||||
```
|
||||
|
||||
**Example Response**:
|
||||
|
||||
```http
|
||||
HTTP/1.1 200
|
||||
Content-Type: application/json
|
||||
|
||||
```
|
||||
|
||||
## Get notification channel by uid
|
||||
|
||||
`GET /api/alert-notifications/uid/:uid`
|
||||
|
||||
Will return the notification channel given the notification channel uid.
|
||||
|
||||
**Example Request**:
|
||||
|
||||
```http
|
||||
GET /api/alert-notifications/uid/team-a-email-notifier HTTP/1.1
|
||||
Accept: application/json
|
||||
Content-Type: application/json
|
||||
Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk
|
||||
```
|
||||
|
||||
**Example Response**:
|
||||
|
||||
```http
|
||||
HTTP/1.1 200
|
||||
Content-Type: application/json
|
||||
|
||||
```
|
||||
|
||||
## Get notification channel by id
|
||||
|
||||
`GET /api/alert-notifications/:id`
|
||||
|
||||
Will return the notification channel given the notification channel id.
|
||||
|
||||
**Example Request**:
|
||||
|
||||
```http
|
||||
GET /api/alert-notifications/1 HTTP/1.1
|
||||
Accept: application/json
|
||||
Content-Type: application/json
|
||||
Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk
|
||||
```
|
||||
|
||||
@@ -47,6 +47,9 @@ Content-Type: application/json
|
||||
Accessible to users with org admin role.
|
||||
|
||||
**Example Request**:
|
||||
|
||||
```http
|
||||
GET /api/org/users HTTP/1.1
|
||||
Accept: application/json
|
||||
Content-Type: application/json
|
||||
Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk
|
||||
@@ -66,9 +69,45 @@ Content-Type: application/json
|
||||
|
||||
Returns all org users within the current organization, but with less detailed information.
|
||||
Accessible to users with org admin role, admin in any folder or admin of any team.
|
||||
```http
|
||||
Mainly used by Grafana UI for providing list of users when adding team members and
|
||||
when editing folder/dashboard permissions.
|
||||
|
||||
Accept: application/json
|
||||
**Example Request**:
|
||||
|
||||
```http
|
||||
GET /api/org/users/lookup HTTP/1.1
|
||||
Accept: application/json
|
||||
Content-Type: application/json
|
||||
Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk
|
||||
```
|
||||
|
||||
**Example Response**:
|
||||
|
||||
```http
|
||||
HTTP/1.1 200
|
||||
Content-Type: application/json
|
||||
|
||||
```
|
||||
|
||||
### Updates the given user
|
||||
|
||||
`PATCH /api/org/users/:userId`
|
||||
|
||||
**Example Request**:
|
||||
|
||||
```http
|
||||
PATCH /api/org/users/1 HTTP/1.1
|
||||
Accept: application/json
|
||||
Content-Type: application/json
|
||||
Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk
|
||||
|
||||
```
|
||||
|
||||
**Example Response**:
|
||||
|
||||
```http
|
||||
HTTP/1.1 200
|
||||
Content-Type: application/json
|
||||
|
||||
```
|
||||
|
||||
|
||||
@@ -6,15 +6,15 @@ import (
|
||||
|
||||
"github.com/grafana/grafana/pkg/api/dtos"
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
m "github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/alerting"
|
||||
"github.com/grafana/grafana/pkg/services/guardian"
|
||||
"github.com/grafana/grafana/pkg/services/search"
|
||||
)
|
||||
|
||||
func ValidateOrgAlert(c *m.ReqContext) {
|
||||
func ValidateOrgAlert(c *models.ReqContext) {
|
||||
id := c.ParamsInt64(":alertId")
|
||||
query := m.GetAlertByIdQuery{Id: id}
|
||||
query := models.GetAlertByIdQuery{Id: id}
|
||||
|
||||
if err := bus.Dispatch(&query); err != nil {
|
||||
c.JsonApiErr(404, "Alert not found", nil)
|
||||
@@ -27,14 +27,14 @@ func ValidateOrgAlert(c *m.ReqContext) {
|
||||
}
|
||||
}
|
||||
|
||||
func GetAlertStatesForDashboard(c *m.ReqContext) Response {
|
||||
func GetAlertStatesForDashboard(c *models.ReqContext) Response {
|
||||
dashboardID := c.QueryInt64("dashboardId")
|
||||
|
||||
if dashboardID == 0 {
|
||||
return Error(400, "Missing query parameter dashboardId", nil)
|
||||
}
|
||||
|
||||
query := m.GetAlertStatesForDashboardQuery{
|
||||
query := models.GetAlertStatesForDashboardQuery{
|
||||
OrgId: c.OrgId,
|
||||
DashboardId: c.QueryInt64("dashboardId"),
|
||||
}
|
||||
@@ -47,7 +47,7 @@ func GetAlertStatesForDashboard(c *m.ReqContext) Response {
|
||||
}
|
||||
|
||||
// GET /api/alerts
|
||||
func GetAlerts(c *m.ReqContext) Response {
|
||||
func GetAlerts(c *models.ReqContext) Response {
|
||||
dashboardQuery := c.Query("dashboardQuery")
|
||||
dashboardTags := c.QueryStrings("dashboardTag")
|
||||
stringDashboardIDs := c.QueryStrings("dashboardId")
|
||||
@@ -79,7 +79,7 @@ func GetAlerts(c *m.ReqContext) Response {
|
||||
DashboardIds: dashboardIDs,
|
||||
Type: string(search.DashHitDB),
|
||||
FolderIds: folderIDs,
|
||||
Permission: m.PERMISSION_VIEW,
|
||||
Permission: models.PERMISSION_VIEW,
|
||||
}
|
||||
|
||||
err := bus.Dispatch(&searchQuery)
|
||||
@@ -95,11 +95,11 @@ func GetAlerts(c *m.ReqContext) Response {
|
||||
|
||||
// if we didn't find any dashboards, return empty result
|
||||
if len(dashboardIDs) == 0 {
|
||||
return JSON(200, []*m.AlertListItemDTO{})
|
||||
return JSON(200, []*models.AlertListItemDTO{})
|
||||
}
|
||||
}
|
||||
|
||||
query := m.GetAlertsQuery{
|
||||
query := models.GetAlertsQuery{
|
||||
OrgId: c.OrgId,
|
||||
DashboardIDs: dashboardIDs,
|
||||
PanelId: c.QueryInt64("panelId"),
|
||||
@@ -118,14 +118,14 @@ func GetAlerts(c *m.ReqContext) Response {
|
||||
}
|
||||
|
||||
for _, alert := range query.Result {
|
||||
alert.Url = m.GetDashboardUrl(alert.DashboardUid, alert.DashboardSlug)
|
||||
alert.Url = models.GetDashboardUrl(alert.DashboardUid, alert.DashboardSlug)
|
||||
}
|
||||
|
||||
return JSON(200, query.Result)
|
||||
}
|
||||
|
||||
// POST /api/alerts/test
|
||||
func AlertTest(c *m.ReqContext, dto dtos.AlertTestCommand) Response {
|
||||
func AlertTest(c *models.ReqContext, dto dtos.AlertTestCommand) Response {
|
||||
if _, idErr := dto.Dashboard.Get("id").Int64(); idErr != nil {
|
||||
return Error(400, "The dashboard needs to be saved at least once before you can test an alert rule", nil)
|
||||
}
|
||||
@@ -141,7 +141,7 @@ func AlertTest(c *m.ReqContext, dto dtos.AlertTestCommand) Response {
|
||||
if validationErr, ok := err.(alerting.ValidationError); ok {
|
||||
return Error(422, validationErr.Error(), nil)
|
||||
}
|
||||
if err == m.ErrDataSourceAccessDenied {
|
||||
if err == models.ErrDataSourceAccessDenied {
|
||||
return Error(403, "Access denied to datasource", err)
|
||||
}
|
||||
return Error(500, "Failed to test rule", err)
|
||||
@@ -171,9 +171,9 @@ func AlertTest(c *m.ReqContext, dto dtos.AlertTestCommand) Response {
|
||||
}
|
||||
|
||||
// GET /api/alerts/:id
|
||||
func GetAlert(c *m.ReqContext) Response {
|
||||
func GetAlert(c *models.ReqContext) Response {
|
||||
id := c.ParamsInt64(":alertId")
|
||||
query := m.GetAlertByIdQuery{Id: id}
|
||||
query := models.GetAlertByIdQuery{Id: id}
|
||||
|
||||
if err := bus.Dispatch(&query); err != nil {
|
||||
return Error(500, "List alerts failed", err)
|
||||
@@ -182,28 +182,52 @@ func GetAlert(c *m.ReqContext) Response {
|
||||
return JSON(200, &query.Result)
|
||||
}
|
||||
|
||||
func GetAlertNotifiers(c *m.ReqContext) Response {
|
||||
func GetAlertNotifiers(c *models.ReqContext) Response {
|
||||
return JSON(200, alerting.GetNotifiers())
|
||||
}
|
||||
|
||||
func GetAlertNotifications(c *m.ReqContext) Response {
|
||||
query := &m.GetAllAlertNotificationsQuery{OrgId: c.OrgId}
|
||||
func GetAlertNotificationLookup(c *models.ReqContext) Response {
|
||||
alertNotifications, err := getAlertNotificationsInternal(c)
|
||||
if err != nil {
|
||||
return Error(500, "Failed to get alert notifications", err)
|
||||
}
|
||||
|
||||
if err := bus.Dispatch(query); err != nil {
|
||||
result := make([]*dtos.AlertNotificationLookup, 0)
|
||||
|
||||
for _, notification := range alertNotifications {
|
||||
result = append(result, dtos.NewAlertNotificationLookup(notification))
|
||||
}
|
||||
|
||||
return JSON(200, result)
|
||||
}
|
||||
|
||||
func GetAlertNotifications(c *models.ReqContext) Response {
|
||||
alertNotifications, err := getAlertNotificationsInternal(c)
|
||||
if err != nil {
|
||||
return Error(500, "Failed to get alert notifications", err)
|
||||
}
|
||||
|
||||
result := make([]*dtos.AlertNotification, 0)
|
||||
|
||||
for _, notification := range query.Result {
|
||||
for _, notification := range alertNotifications {
|
||||
result = append(result, dtos.NewAlertNotification(notification))
|
||||
}
|
||||
|
||||
return JSON(200, result)
|
||||
}
|
||||
|
||||
func GetAlertNotificationByID(c *m.ReqContext) Response {
|
||||
query := &m.GetAlertNotificationsQuery{
|
||||
func getAlertNotificationsInternal(c *models.ReqContext) ([]*models.AlertNotification, error) {
|
||||
query := &models.GetAllAlertNotificationsQuery{OrgId: c.OrgId}
|
||||
|
||||
if err := bus.Dispatch(query); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return query.Result, nil
|
||||
}
|
||||
|
||||
func GetAlertNotificationByID(c *models.ReqContext) Response {
|
||||
query := &models.GetAlertNotificationsQuery{
|
||||
OrgId: c.OrgId,
|
||||
Id: c.ParamsInt64("notificationId"),
|
||||
}
|
||||
@@ -223,8 +247,8 @@ func GetAlertNotificationByID(c *m.ReqContext) Response {
|
||||
return JSON(200, dtos.NewAlertNotification(query.Result))
|
||||
}
|
||||
|
||||
func GetAlertNotificationByUID(c *m.ReqContext) Response {
|
||||
query := &m.GetAlertNotificationsWithUidQuery{
|
||||
func GetAlertNotificationByUID(c *models.ReqContext) Response {
|
||||
query := &models.GetAlertNotificationsWithUidQuery{
|
||||
OrgId: c.OrgId,
|
||||
Uid: c.Params("uid"),
|
||||
}
|
||||
@@ -244,7 +268,7 @@ func GetAlertNotificationByUID(c *m.ReqContext) Response {
|
||||
return JSON(200, dtos.NewAlertNotification(query.Result))
|
||||
}
|
||||
|
||||
func CreateAlertNotification(c *m.ReqContext, cmd m.CreateAlertNotificationCommand) Response {
|
||||
func CreateAlertNotification(c *models.ReqContext, cmd models.CreateAlertNotificationCommand) Response {
|
||||
cmd.OrgId = c.OrgId
|
||||
|
||||
if err := bus.Dispatch(&cmd); err != nil {
|
||||
@@ -254,7 +278,7 @@ func CreateAlertNotification(c *m.ReqContext, cmd m.CreateAlertNotificationComma
|
||||
return JSON(200, dtos.NewAlertNotification(cmd.Result))
|
||||
}
|
||||
|
||||
func UpdateAlertNotification(c *m.ReqContext, cmd m.UpdateAlertNotificationCommand) Response {
|
||||
func UpdateAlertNotification(c *models.ReqContext, cmd models.UpdateAlertNotificationCommand) Response {
|
||||
cmd.OrgId = c.OrgId
|
||||
|
||||
if err := bus.Dispatch(&cmd); err != nil {
|
||||
@@ -268,7 +292,7 @@ func UpdateAlertNotification(c *m.ReqContext, cmd m.UpdateAlertNotificationComma
|
||||
return JSON(200, dtos.NewAlertNotification(cmd.Result))
|
||||
}
|
||||
|
||||
func UpdateAlertNotificationByUID(c *m.ReqContext, cmd m.UpdateAlertNotificationWithUidCommand) Response {
|
||||
func UpdateAlertNotificationByUID(c *models.ReqContext, cmd models.UpdateAlertNotificationWithUidCommand) Response {
|
||||
cmd.OrgId = c.OrgId
|
||||
cmd.Uid = c.Params("uid")
|
||||
|
||||
@@ -283,8 +307,8 @@ func UpdateAlertNotificationByUID(c *m.ReqContext, cmd m.UpdateAlertNotification
|
||||
return JSON(200, dtos.NewAlertNotification(cmd.Result))
|
||||
}
|
||||
|
||||
func DeleteAlertNotification(c *m.ReqContext) Response {
|
||||
cmd := m.DeleteAlertNotificationCommand{
|
||||
func DeleteAlertNotification(c *models.ReqContext) Response {
|
||||
cmd := models.DeleteAlertNotificationCommand{
|
||||
OrgId: c.OrgId,
|
||||
Id: c.ParamsInt64("notificationId"),
|
||||
}
|
||||
@@ -296,8 +320,8 @@ func DeleteAlertNotification(c *m.ReqContext) Response {
|
||||
return Success("Notification deleted")
|
||||
}
|
||||
|
||||
func DeleteAlertNotificationByUID(c *m.ReqContext) Response {
|
||||
cmd := m.DeleteAlertNotificationWithUidCommand{
|
||||
func DeleteAlertNotificationByUID(c *models.ReqContext) Response {
|
||||
cmd := models.DeleteAlertNotificationWithUidCommand{
|
||||
OrgId: c.OrgId,
|
||||
Uid: c.Params("uid"),
|
||||
}
|
||||
@@ -310,7 +334,7 @@ func DeleteAlertNotificationByUID(c *m.ReqContext) Response {
|
||||
}
|
||||
|
||||
//POST /api/alert-notifications/test
|
||||
func NotificationTest(c *m.ReqContext, dto dtos.NotificationTestCommand) Response {
|
||||
func NotificationTest(c *models.ReqContext, dto dtos.NotificationTestCommand) Response {
|
||||
cmd := &alerting.NotificationTestCommand{
|
||||
Name: dto.Name,
|
||||
Type: dto.Type,
|
||||
@@ -318,7 +342,7 @@ func NotificationTest(c *m.ReqContext, dto dtos.NotificationTestCommand) Respons
|
||||
}
|
||||
|
||||
if err := bus.Dispatch(cmd); err != nil {
|
||||
if err == m.ErrSmtpNotEnabled {
|
||||
if err == models.ErrSmtpNotEnabled {
|
||||
return Error(412, err.Error(), err)
|
||||
}
|
||||
return Error(500, "Failed to send alert notifications", err)
|
||||
@@ -328,10 +352,10 @@ func NotificationTest(c *m.ReqContext, dto dtos.NotificationTestCommand) Respons
|
||||
}
|
||||
|
||||
//POST /api/alerts/:alertId/pause
|
||||
func PauseAlert(c *m.ReqContext, dto dtos.PauseAlertCommand) Response {
|
||||
func PauseAlert(c *models.ReqContext, dto dtos.PauseAlertCommand) Response {
|
||||
alertID := c.ParamsInt64("alertId")
|
||||
|
||||
query := m.GetAlertByIdQuery{Id: alertID}
|
||||
query := models.GetAlertByIdQuery{Id: alertID}
|
||||
|
||||
if err := bus.Dispatch(&query); err != nil {
|
||||
return Error(500, "Get Alert failed", err)
|
||||
@@ -346,7 +370,7 @@ func PauseAlert(c *m.ReqContext, dto dtos.PauseAlertCommand) Response {
|
||||
return Error(403, "Access denied to this dashboard and alert", nil)
|
||||
}
|
||||
|
||||
cmd := m.PauseAlertCommand{
|
||||
cmd := models.PauseAlertCommand{
|
||||
OrgId: c.OrgId,
|
||||
AlertIds: []int64{alertID},
|
||||
Paused: dto.Paused,
|
||||
@@ -356,10 +380,10 @@ func PauseAlert(c *m.ReqContext, dto dtos.PauseAlertCommand) Response {
|
||||
return Error(500, "", err)
|
||||
}
|
||||
|
||||
var response m.AlertStateType = m.AlertStateUnknown
|
||||
var response models.AlertStateType = models.AlertStateUnknown
|
||||
pausedState := "un-paused"
|
||||
if cmd.Paused {
|
||||
response = m.AlertStatePaused
|
||||
response = models.AlertStatePaused
|
||||
pausedState = "paused"
|
||||
}
|
||||
|
||||
@@ -373,8 +397,8 @@ func PauseAlert(c *m.ReqContext, dto dtos.PauseAlertCommand) Response {
|
||||
}
|
||||
|
||||
//POST /api/admin/pause-all-alerts
|
||||
func PauseAllAlerts(c *m.ReqContext, dto dtos.PauseAllAlertsCommand) Response {
|
||||
updateCmd := m.PauseAllAlertCommand{
|
||||
func PauseAllAlerts(c *models.ReqContext, dto dtos.PauseAllAlertsCommand) Response {
|
||||
updateCmd := models.PauseAllAlertCommand{
|
||||
Paused: dto.Paused,
|
||||
}
|
||||
|
||||
@@ -382,10 +406,10 @@ func PauseAllAlerts(c *m.ReqContext, dto dtos.PauseAllAlertsCommand) Response {
|
||||
return Error(500, "Failed to pause alerts", err)
|
||||
}
|
||||
|
||||
var response m.AlertStateType = m.AlertStatePending
|
||||
var response models.AlertStateType = models.AlertStatePending
|
||||
pausedState := "un paused"
|
||||
if updateCmd.Paused {
|
||||
response = m.AlertStatePaused
|
||||
response = models.AlertStatePaused
|
||||
pausedState = "paused"
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
|
||||
"github.com/grafana/grafana/pkg/api/dtos"
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
m "github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/search"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
@@ -14,24 +14,24 @@ import (
|
||||
func TestAlertingApiEndpoint(t *testing.T) {
|
||||
Convey("Given an alert in a dashboard with an acl", t, func() {
|
||||
|
||||
singleAlert := &m.Alert{Id: 1, DashboardId: 1, Name: "singlealert"}
|
||||
singleAlert := &models.Alert{Id: 1, DashboardId: 1, Name: "singlealert"}
|
||||
|
||||
bus.AddHandler("test", func(query *m.GetAlertByIdQuery) error {
|
||||
bus.AddHandler("test", func(query *models.GetAlertByIdQuery) error {
|
||||
query.Result = singleAlert
|
||||
return nil
|
||||
})
|
||||
|
||||
viewerRole := m.ROLE_VIEWER
|
||||
editorRole := m.ROLE_EDITOR
|
||||
viewerRole := models.ROLE_VIEWER
|
||||
editorRole := models.ROLE_EDITOR
|
||||
|
||||
aclMockResp := []*m.DashboardAclInfoDTO{}
|
||||
bus.AddHandler("test", func(query *m.GetDashboardAclInfoListQuery) error {
|
||||
aclMockResp := []*models.DashboardAclInfoDTO{}
|
||||
bus.AddHandler("test", func(query *models.GetDashboardAclInfoListQuery) error {
|
||||
query.Result = aclMockResp
|
||||
return nil
|
||||
})
|
||||
|
||||
bus.AddHandler("test", func(query *m.GetTeamsByUserQuery) error {
|
||||
query.Result = []*m.TeamDTO{}
|
||||
bus.AddHandler("test", func(query *models.GetTeamsByUserQuery) error {
|
||||
query.Result = []*models.TeamDTO{}
|
||||
return nil
|
||||
})
|
||||
|
||||
@@ -41,7 +41,7 @@ func TestAlertingApiEndpoint(t *testing.T) {
|
||||
AlertId: 1,
|
||||
Paused: true,
|
||||
}
|
||||
postAlertScenario("When calling POST on", "/api/alerts/1/pause", "/api/alerts/:alertId/pause", m.ROLE_EDITOR, cmd, func(sc *scenarioContext) {
|
||||
postAlertScenario("When calling POST on", "/api/alerts/1/pause", "/api/alerts/:alertId/pause", models.ROLE_EDITOR, cmd, func(sc *scenarioContext) {
|
||||
CallPauseAlert(sc)
|
||||
So(sc.resp.Code, ShouldEqual, 403)
|
||||
})
|
||||
@@ -49,9 +49,9 @@ func TestAlertingApiEndpoint(t *testing.T) {
|
||||
})
|
||||
|
||||
Convey("When user is editor and dashboard has default ACL", func() {
|
||||
aclMockResp = []*m.DashboardAclInfoDTO{
|
||||
{Role: &viewerRole, Permission: m.PERMISSION_VIEW},
|
||||
{Role: &editorRole, Permission: m.PERMISSION_EDIT},
|
||||
aclMockResp = []*models.DashboardAclInfoDTO{
|
||||
{Role: &viewerRole, Permission: models.PERMISSION_VIEW},
|
||||
{Role: &editorRole, Permission: models.PERMISSION_EDIT},
|
||||
}
|
||||
|
||||
Convey("Should be able to pause the alert", func() {
|
||||
@@ -59,22 +59,22 @@ func TestAlertingApiEndpoint(t *testing.T) {
|
||||
AlertId: 1,
|
||||
Paused: true,
|
||||
}
|
||||
postAlertScenario("When calling POST on", "/api/alerts/1/pause", "/api/alerts/:alertId/pause", m.ROLE_EDITOR, cmd, func(sc *scenarioContext) {
|
||||
postAlertScenario("When calling POST on", "/api/alerts/1/pause", "/api/alerts/:alertId/pause", models.ROLE_EDITOR, cmd, func(sc *scenarioContext) {
|
||||
CallPauseAlert(sc)
|
||||
So(sc.resp.Code, ShouldEqual, 200)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
loggedInUserScenarioWithRole("When calling GET on", "GET", "/api/alerts?dashboardId=1", "/api/alerts", m.ROLE_EDITOR, func(sc *scenarioContext) {
|
||||
loggedInUserScenarioWithRole("When calling GET on", "GET", "/api/alerts?dashboardId=1", "/api/alerts", models.ROLE_EDITOR, func(sc *scenarioContext) {
|
||||
var searchQuery *search.Query
|
||||
bus.AddHandler("test", func(query *search.Query) error {
|
||||
searchQuery = query
|
||||
return nil
|
||||
})
|
||||
|
||||
var getAlertsQuery *m.GetAlertsQuery
|
||||
bus.AddHandler("test", func(query *m.GetAlertsQuery) error {
|
||||
var getAlertsQuery *models.GetAlertsQuery
|
||||
bus.AddHandler("test", func(query *models.GetAlertsQuery) error {
|
||||
getAlertsQuery = query
|
||||
return nil
|
||||
})
|
||||
@@ -86,7 +86,7 @@ func TestAlertingApiEndpoint(t *testing.T) {
|
||||
So(getAlertsQuery, ShouldNotBeNil)
|
||||
})
|
||||
|
||||
loggedInUserScenarioWithRole("When calling GET on", "GET", "/api/alerts?dashboardId=1&dashboardId=2&folderId=3&dashboardTag=abc&dashboardQuery=dbQuery&limit=5&query=alertQuery", "/api/alerts", m.ROLE_EDITOR, func(sc *scenarioContext) {
|
||||
loggedInUserScenarioWithRole("When calling GET on", "GET", "/api/alerts?dashboardId=1&dashboardId=2&folderId=3&dashboardTag=abc&dashboardQuery=dbQuery&limit=5&query=alertQuery", "/api/alerts", models.ROLE_EDITOR, func(sc *scenarioContext) {
|
||||
var searchQuery *search.Query
|
||||
bus.AddHandler("test", func(query *search.Query) error {
|
||||
searchQuery = query
|
||||
@@ -97,8 +97,8 @@ func TestAlertingApiEndpoint(t *testing.T) {
|
||||
return nil
|
||||
})
|
||||
|
||||
var getAlertsQuery *m.GetAlertsQuery
|
||||
bus.AddHandler("test", func(query *m.GetAlertsQuery) error {
|
||||
var getAlertsQuery *models.GetAlertsQuery
|
||||
bus.AddHandler("test", func(query *models.GetAlertsQuery) error {
|
||||
getAlertsQuery = query
|
||||
return nil
|
||||
})
|
||||
@@ -120,7 +120,7 @@ func TestAlertingApiEndpoint(t *testing.T) {
|
||||
So(getAlertsQuery.Query, ShouldEqual, "alertQuery")
|
||||
})
|
||||
|
||||
loggedInUserScenarioWithRole("When calling GET on", "GET", "/api/alert-notifications/1", "/alert-notifications/:notificationId", m.ROLE_ADMIN, func(sc *scenarioContext) {
|
||||
loggedInUserScenarioWithRole("When calling GET on", "GET", "/api/alert-notifications/1", "/alert-notifications/:notificationId", models.ROLE_ADMIN, func(sc *scenarioContext) {
|
||||
sc.handlerFunc = GetAlertNotificationByID
|
||||
sc.fakeReqWithParams("GET", sc.url, map[string]string{}).exec()
|
||||
So(sc.resp.Code, ShouldEqual, 404)
|
||||
@@ -129,19 +129,19 @@ func TestAlertingApiEndpoint(t *testing.T) {
|
||||
}
|
||||
|
||||
func CallPauseAlert(sc *scenarioContext) {
|
||||
bus.AddHandler("test", func(cmd *m.PauseAlertCommand) error {
|
||||
bus.AddHandler("test", func(cmd *models.PauseAlertCommand) error {
|
||||
return nil
|
||||
})
|
||||
|
||||
sc.fakeReqWithParams("POST", sc.url, map[string]string{}).exec()
|
||||
}
|
||||
|
||||
func postAlertScenario(desc string, url string, routePattern string, role m.RoleType, cmd dtos.PauseAlertCommand, fn scenarioFunc) {
|
||||
func postAlertScenario(desc string, url string, routePattern string, role models.RoleType, cmd dtos.PauseAlertCommand, fn scenarioFunc) {
|
||||
Convey(desc+" "+url, func() {
|
||||
defer bus.ClearBusHandlers()
|
||||
|
||||
sc := setupScenarioContext(url)
|
||||
sc.defaultHandler = Wrap(func(c *m.ReqContext) Response {
|
||||
sc.defaultHandler = Wrap(func(c *models.ReqContext) Response {
|
||||
sc.context = c
|
||||
sc.context.UserId = TestUserID
|
||||
sc.context.OrgId = TestOrgID
|
||||
|
||||
@@ -183,6 +183,7 @@ func (hs *HTTPServer) registerRoutes() {
|
||||
apiRoute.Group("/org", func(orgRoute routing.RouteRegister) {
|
||||
orgRoute.Put("/", bind(dtos.UpdateOrgForm{}), Wrap(UpdateOrgCurrent))
|
||||
orgRoute.Put("/address", bind(dtos.UpdateOrgAddressForm{}), Wrap(UpdateOrgAddressCurrent))
|
||||
orgRoute.Get("/users", Wrap(GetOrgUsersForCurrentOrg))
|
||||
orgRoute.Post("/users", quota("user"), bind(models.AddOrgUserCommand{}), Wrap(AddOrgUserToCurrentOrg))
|
||||
orgRoute.Patch("/users/:userId", bind(models.UpdateOrgUserCommand{}), Wrap(UpdateOrgUserForCurrentOrg))
|
||||
orgRoute.Delete("/users/:userId", Wrap(RemoveOrgUserForCurrentOrg))
|
||||
@@ -199,7 +200,7 @@ func (hs *HTTPServer) registerRoutes() {
|
||||
|
||||
// current org without requirement of user to be org admin
|
||||
apiRoute.Group("/org", func(orgRoute routing.RouteRegister) {
|
||||
orgRoute.Get("/users", Wrap(GetOrgUsersForCurrentOrg))
|
||||
orgRoute.Get("/users/lookup", Wrap(GetOrgUsersForCurrentOrgLookup))
|
||||
})
|
||||
|
||||
// create new org
|
||||
@@ -343,10 +344,10 @@ func (hs *HTTPServer) registerRoutes() {
|
||||
alertsRoute.Get("/states-for-dashboard", Wrap(GetAlertStatesForDashboard))
|
||||
})
|
||||
|
||||
apiRoute.Get("/alert-notifications", Wrap(GetAlertNotifications))
|
||||
apiRoute.Get("/alert-notifiers", Wrap(GetAlertNotifiers))
|
||||
apiRoute.Get("/alert-notifiers", reqEditorRole, Wrap(GetAlertNotifiers))
|
||||
|
||||
apiRoute.Group("/alert-notifications", func(alertNotifications routing.RouteRegister) {
|
||||
alertNotifications.Get("/", Wrap(GetAlertNotifications))
|
||||
alertNotifications.Post("/test", bind(dtos.NotificationTestCommand{}), Wrap(NotificationTest))
|
||||
alertNotifications.Post("/", bind(models.CreateAlertNotificationCommand{}), Wrap(CreateAlertNotification))
|
||||
alertNotifications.Put("/:notificationId", bind(models.UpdateAlertNotificationCommand{}), Wrap(UpdateAlertNotification))
|
||||
@@ -357,6 +358,11 @@ func (hs *HTTPServer) registerRoutes() {
|
||||
alertNotifications.Delete("/uid/:uid", Wrap(DeleteAlertNotificationByUID))
|
||||
}, reqEditorRole)
|
||||
|
||||
// alert notifications without requirement of user to be org editor
|
||||
apiRoute.Group("/alert-notifications", func(orgRoute routing.RouteRegister) {
|
||||
orgRoute.Get("/lookup", Wrap(GetAlertNotificationLookup))
|
||||
})
|
||||
|
||||
apiRoute.Get("/annotations", Wrap(GetAnnotations))
|
||||
apiRoute.Post("/annotations/mass-delete", reqOrgAdmin, bind(dtos.DeleteAnnotationsCmd{}), Wrap(DeleteAnnotations))
|
||||
|
||||
|
||||
@@ -77,6 +77,24 @@ type AlertNotification struct {
|
||||
Settings *simplejson.Json `json:"settings"`
|
||||
}
|
||||
|
||||
func NewAlertNotificationLookup(notification *models.AlertNotification) *AlertNotificationLookup {
|
||||
return &AlertNotificationLookup{
|
||||
Id: notification.Id,
|
||||
Uid: notification.Uid,
|
||||
Name: notification.Name,
|
||||
Type: notification.Type,
|
||||
IsDefault: notification.IsDefault,
|
||||
}
|
||||
}
|
||||
|
||||
type AlertNotificationLookup struct {
|
||||
Id int64 `json:"id"`
|
||||
Uid string `json:"uid"`
|
||||
Name string `json:"name"`
|
||||
Type string `json:"type"`
|
||||
IsDefault bool `json:"isDefault"`
|
||||
}
|
||||
|
||||
type AlertTestCommand struct {
|
||||
Dashboard *simplejson.Json `json:"dashboard" binding:"Required"`
|
||||
PanelId int64 `json:"panelId" binding:"Required"`
|
||||
|
||||
@@ -50,3 +50,9 @@ type ResetUserPasswordForm struct {
|
||||
NewPassword string `json:"newPassword"`
|
||||
ConfirmPassword string `json:"confirmPassword"`
|
||||
}
|
||||
|
||||
type UserLookupDTO struct {
|
||||
UserID int64 `json:"userId"`
|
||||
Login string `json:"login"`
|
||||
AvatarURL string `json:"avatarUrl"`
|
||||
}
|
||||
|
||||
@@ -3,27 +3,27 @@ package api
|
||||
import (
|
||||
"github.com/grafana/grafana/pkg/api/dtos"
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
m "github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
)
|
||||
|
||||
// POST /api/org/users
|
||||
func AddOrgUserToCurrentOrg(c *m.ReqContext, cmd m.AddOrgUserCommand) Response {
|
||||
func AddOrgUserToCurrentOrg(c *models.ReqContext, cmd models.AddOrgUserCommand) Response {
|
||||
cmd.OrgId = c.OrgId
|
||||
return addOrgUserHelper(cmd)
|
||||
}
|
||||
|
||||
// POST /api/orgs/:orgId/users
|
||||
func AddOrgUser(c *m.ReqContext, cmd m.AddOrgUserCommand) Response {
|
||||
func AddOrgUser(c *models.ReqContext, cmd models.AddOrgUserCommand) Response {
|
||||
cmd.OrgId = c.ParamsInt64(":orgId")
|
||||
return addOrgUserHelper(cmd)
|
||||
}
|
||||
|
||||
func addOrgUserHelper(cmd m.AddOrgUserCommand) Response {
|
||||
func addOrgUserHelper(cmd models.AddOrgUserCommand) Response {
|
||||
if !cmd.Role.IsValid() {
|
||||
return Error(400, "Invalid role specified", nil)
|
||||
}
|
||||
|
||||
userQuery := m.GetUserByLoginQuery{LoginOrEmail: cmd.LoginOrEmail}
|
||||
userQuery := models.GetUserByLoginQuery{LoginOrEmail: cmd.LoginOrEmail}
|
||||
err := bus.Dispatch(&userQuery)
|
||||
if err != nil {
|
||||
return Error(404, "User not found", nil)
|
||||
@@ -34,7 +34,7 @@ func addOrgUserHelper(cmd m.AddOrgUserCommand) Response {
|
||||
cmd.UserId = userToAdd.Id
|
||||
|
||||
if err := bus.Dispatch(&cmd); err != nil {
|
||||
if err == m.ErrOrgUserAlreadyAdded {
|
||||
if err == models.ErrOrgUserAlreadyAdded {
|
||||
return Error(409, "User is already member of this organization", nil)
|
||||
}
|
||||
return Error(500, "Could not add user to organization", err)
|
||||
@@ -44,54 +44,115 @@ func addOrgUserHelper(cmd m.AddOrgUserCommand) Response {
|
||||
}
|
||||
|
||||
// GET /api/org/users
|
||||
func GetOrgUsersForCurrentOrg(c *m.ReqContext) Response {
|
||||
return getOrgUsersHelper(c.OrgId, c.Query("query"), c.QueryInt("limit"))
|
||||
func GetOrgUsersForCurrentOrg(c *models.ReqContext) Response {
|
||||
result, err := getOrgUsersHelper(c.OrgId, c.Query("query"), c.QueryInt("limit"))
|
||||
if err != nil {
|
||||
return Error(500, "Failed to get users for current organization", err)
|
||||
}
|
||||
|
||||
return JSON(200, result)
|
||||
}
|
||||
|
||||
// GET /api/org/users/lookup
|
||||
func GetOrgUsersForCurrentOrgLookup(c *models.ReqContext) Response {
|
||||
isAdmin, err := isOrgAdminFolderAdminOrTeamAdmin(c)
|
||||
if err != nil {
|
||||
return Error(500, "Failed to get users for current organization", err)
|
||||
}
|
||||
|
||||
if !isAdmin {
|
||||
return Error(403, "Permission denied", nil)
|
||||
}
|
||||
|
||||
orgUsers, err := getOrgUsersHelper(c.OrgId, c.Query("query"), c.QueryInt("limit"))
|
||||
if err != nil {
|
||||
return Error(500, "Failed to get users for current organization", err)
|
||||
}
|
||||
|
||||
result := make([]*dtos.UserLookupDTO, 0)
|
||||
|
||||
for _, u := range orgUsers {
|
||||
result = append(result, &dtos.UserLookupDTO{
|
||||
UserID: u.UserId,
|
||||
Login: u.Login,
|
||||
AvatarURL: u.AvatarUrl,
|
||||
})
|
||||
}
|
||||
|
||||
return JSON(200, result)
|
||||
}
|
||||
|
||||
func isOrgAdminFolderAdminOrTeamAdmin(c *models.ReqContext) (bool, error) {
|
||||
if c.OrgRole == models.ROLE_ADMIN {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
hasAdminPermissionInFoldersQuery := models.HasAdminPermissionInFoldersQuery{SignedInUser: c.SignedInUser}
|
||||
if err := bus.Dispatch(&hasAdminPermissionInFoldersQuery); err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if hasAdminPermissionInFoldersQuery.Result {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
isAdminOfTeamsQuery := models.IsAdminOfTeamsQuery{SignedInUser: c.SignedInUser}
|
||||
if err := bus.Dispatch(&isAdminOfTeamsQuery); err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return isAdminOfTeamsQuery.Result, nil
|
||||
}
|
||||
|
||||
// GET /api/orgs/:orgId/users
|
||||
func GetOrgUsers(c *m.ReqContext) Response {
|
||||
return getOrgUsersHelper(c.ParamsInt64(":orgId"), "", 0)
|
||||
func GetOrgUsers(c *models.ReqContext) Response {
|
||||
result, err := getOrgUsersHelper(c.ParamsInt64(":orgId"), "", 0)
|
||||
if err != nil {
|
||||
return Error(500, "Failed to get users for organization", err)
|
||||
}
|
||||
|
||||
func getOrgUsersHelper(orgID int64, query string, limit int) Response {
|
||||
q := m.GetOrgUsersQuery{
|
||||
return JSON(200, result)
|
||||
}
|
||||
|
||||
func getOrgUsersHelper(orgID int64, query string, limit int) ([]*models.OrgUserDTO, error) {
|
||||
q := models.GetOrgUsersQuery{
|
||||
OrgId: orgID,
|
||||
Query: query,
|
||||
Limit: limit,
|
||||
}
|
||||
|
||||
if err := bus.Dispatch(&q); err != nil {
|
||||
return Error(500, "Failed to get account user", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, user := range q.Result {
|
||||
user.AvatarUrl = dtos.GetGravatarUrl(user.Email)
|
||||
}
|
||||
|
||||
return JSON(200, q.Result)
|
||||
return q.Result, nil
|
||||
}
|
||||
|
||||
// PATCH /api/org/users/:userId
|
||||
func UpdateOrgUserForCurrentOrg(c *m.ReqContext, cmd m.UpdateOrgUserCommand) Response {
|
||||
func UpdateOrgUserForCurrentOrg(c *models.ReqContext, cmd models.UpdateOrgUserCommand) Response {
|
||||
cmd.OrgId = c.OrgId
|
||||
cmd.UserId = c.ParamsInt64(":userId")
|
||||
return updateOrgUserHelper(cmd)
|
||||
}
|
||||
|
||||
// PATCH /api/orgs/:orgId/users/:userId
|
||||
func UpdateOrgUser(c *m.ReqContext, cmd m.UpdateOrgUserCommand) Response {
|
||||
func UpdateOrgUser(c *models.ReqContext, cmd models.UpdateOrgUserCommand) Response {
|
||||
cmd.OrgId = c.ParamsInt64(":orgId")
|
||||
cmd.UserId = c.ParamsInt64(":userId")
|
||||
return updateOrgUserHelper(cmd)
|
||||
}
|
||||
|
||||
func updateOrgUserHelper(cmd m.UpdateOrgUserCommand) Response {
|
||||
func updateOrgUserHelper(cmd models.UpdateOrgUserCommand) Response {
|
||||
if !cmd.Role.IsValid() {
|
||||
return Error(400, "Invalid role specified", nil)
|
||||
}
|
||||
|
||||
if err := bus.Dispatch(&cmd); err != nil {
|
||||
if err == m.ErrLastOrgAdmin {
|
||||
if err == models.ErrLastOrgAdmin {
|
||||
return Error(400, "Cannot change role so that there is no organization admin left", nil)
|
||||
}
|
||||
return Error(500, "Failed update org user", err)
|
||||
@@ -101,8 +162,8 @@ func updateOrgUserHelper(cmd m.UpdateOrgUserCommand) Response {
|
||||
}
|
||||
|
||||
// DELETE /api/org/users/:userId
|
||||
func RemoveOrgUserForCurrentOrg(c *m.ReqContext) Response {
|
||||
return removeOrgUserHelper(&m.RemoveOrgUserCommand{
|
||||
func RemoveOrgUserForCurrentOrg(c *models.ReqContext) Response {
|
||||
return removeOrgUserHelper(&models.RemoveOrgUserCommand{
|
||||
UserId: c.ParamsInt64(":userId"),
|
||||
OrgId: c.OrgId,
|
||||
ShouldDeleteOrphanedUser: true,
|
||||
@@ -110,16 +171,16 @@ func RemoveOrgUserForCurrentOrg(c *m.ReqContext) Response {
|
||||
}
|
||||
|
||||
// DELETE /api/orgs/:orgId/users/:userId
|
||||
func RemoveOrgUser(c *m.ReqContext) Response {
|
||||
return removeOrgUserHelper(&m.RemoveOrgUserCommand{
|
||||
func RemoveOrgUser(c *models.ReqContext) Response {
|
||||
return removeOrgUserHelper(&models.RemoveOrgUserCommand{
|
||||
UserId: c.ParamsInt64(":userId"),
|
||||
OrgId: c.ParamsInt64(":orgId"),
|
||||
})
|
||||
}
|
||||
|
||||
func removeOrgUserHelper(cmd *m.RemoveOrgUserCommand) Response {
|
||||
func removeOrgUserHelper(cmd *models.RemoveOrgUserCommand) Response {
|
||||
if err := bus.Dispatch(cmd); err != nil {
|
||||
if err == m.ErrLastOrgAdmin {
|
||||
if err == models.ErrLastOrgAdmin {
|
||||
return Error(400, "Cannot remove last organization admin", nil)
|
||||
}
|
||||
return Error(500, "Failed to remove user from organization", err)
|
||||
|
||||
@@ -98,3 +98,8 @@ type HasEditPermissionInFoldersQuery struct {
|
||||
SignedInUser *SignedInUser
|
||||
Result bool
|
||||
}
|
||||
|
||||
type HasAdminPermissionInFoldersQuery struct {
|
||||
SignedInUser *SignedInUser
|
||||
Result bool
|
||||
}
|
||||
|
||||
@@ -88,3 +88,8 @@ type SearchTeamQueryResult struct {
|
||||
Page int `json:"page"`
|
||||
PerPage int `json:"perPage"`
|
||||
}
|
||||
|
||||
type IsAdminOfTeamsQuery struct {
|
||||
SignedInUser *SignedInUser
|
||||
Result bool
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
"github.com/grafana/grafana/pkg/infra/metrics"
|
||||
m "github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/search"
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
)
|
||||
@@ -25,17 +25,18 @@ func init() {
|
||||
bus.AddHandler("sql", GetDashboardsBySlug)
|
||||
bus.AddHandler("sql", ValidateDashboardBeforeSave)
|
||||
bus.AddHandler("sql", HasEditPermissionInFolders)
|
||||
bus.AddHandler("sql", HasAdminPermissionInFolders)
|
||||
}
|
||||
|
||||
var generateNewUid func() string = util.GenerateShortUID
|
||||
|
||||
func SaveDashboard(cmd *m.SaveDashboardCommand) error {
|
||||
func SaveDashboard(cmd *models.SaveDashboardCommand) error {
|
||||
return inTransaction(func(sess *DBSession) error {
|
||||
return saveDashboard(sess, cmd)
|
||||
})
|
||||
}
|
||||
|
||||
func saveDashboard(sess *DBSession, cmd *m.SaveDashboardCommand) error {
|
||||
func saveDashboard(sess *DBSession, cmd *models.SaveDashboardCommand) error {
|
||||
dash := cmd.GetDashboardModel()
|
||||
|
||||
userId := cmd.UserId
|
||||
@@ -45,13 +46,13 @@ func saveDashboard(sess *DBSession, cmd *m.SaveDashboardCommand) error {
|
||||
}
|
||||
|
||||
if dash.Id > 0 {
|
||||
var existing m.Dashboard
|
||||
var existing models.Dashboard
|
||||
dashWithIdExists, err := sess.Where("id=? AND org_id=?", dash.Id, dash.OrgId).Get(&existing)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !dashWithIdExists {
|
||||
return m.ErrDashboardNotFound
|
||||
return models.ErrDashboardNotFound
|
||||
}
|
||||
|
||||
// check for is someone else has written in between
|
||||
@@ -59,13 +60,13 @@ func saveDashboard(sess *DBSession, cmd *m.SaveDashboardCommand) error {
|
||||
if cmd.Overwrite {
|
||||
dash.SetVersion(existing.Version)
|
||||
} else {
|
||||
return m.ErrDashboardVersionMismatch
|
||||
return models.ErrDashboardVersionMismatch
|
||||
}
|
||||
}
|
||||
|
||||
// do not allow plugin dashboard updates without overwrite flag
|
||||
if existing.PluginId != "" && !cmd.Overwrite {
|
||||
return m.UpdatePluginDashboardError{PluginId: existing.PluginId}
|
||||
return models.UpdatePluginDashboardError{PluginId: existing.PluginId}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -108,10 +109,10 @@ func saveDashboard(sess *DBSession, cmd *m.SaveDashboardCommand) error {
|
||||
}
|
||||
|
||||
if affectedRows == 0 {
|
||||
return m.ErrDashboardNotFound
|
||||
return models.ErrDashboardNotFound
|
||||
}
|
||||
|
||||
dashVersion := &m.DashboardVersion{
|
||||
dashVersion := &models.DashboardVersion{
|
||||
DashboardId: dash.Id,
|
||||
ParentVersion: parentVersion,
|
||||
RestoredFrom: cmd.RestoredFrom,
|
||||
@@ -126,7 +127,7 @@ func saveDashboard(sess *DBSession, cmd *m.SaveDashboardCommand) error {
|
||||
if affectedRows, err = sess.Insert(dashVersion); err != nil {
|
||||
return err
|
||||
} else if affectedRows == 0 {
|
||||
return m.ErrDashboardNotFound
|
||||
return models.ErrDashboardNotFound
|
||||
}
|
||||
|
||||
// delete existing tags
|
||||
@@ -154,7 +155,7 @@ func generateNewDashboardUid(sess *DBSession, orgId int64) (string, error) {
|
||||
for i := 0; i < 3; i++ {
|
||||
uid := generateNewUid()
|
||||
|
||||
exists, err := sess.Where("org_id=? AND uid=?", orgId, uid).Get(&m.Dashboard{})
|
||||
exists, err := sess.Where("org_id=? AND uid=?", orgId, uid).Get(&models.Dashboard{})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@@ -164,17 +165,17 @@ func generateNewDashboardUid(sess *DBSession, orgId int64) (string, error) {
|
||||
}
|
||||
}
|
||||
|
||||
return "", m.ErrDashboardFailedGenerateUniqueUid
|
||||
return "", models.ErrDashboardFailedGenerateUniqueUid
|
||||
}
|
||||
|
||||
func GetDashboard(query *m.GetDashboardQuery) error {
|
||||
dashboard := m.Dashboard{Slug: query.Slug, OrgId: query.OrgId, Id: query.Id, Uid: query.Uid}
|
||||
func GetDashboard(query *models.GetDashboardQuery) error {
|
||||
dashboard := models.Dashboard{Slug: query.Slug, OrgId: query.OrgId, Id: query.Id, Uid: query.Uid}
|
||||
has, err := x.Get(&dashboard)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
} else if !has {
|
||||
return m.ErrDashboardNotFound
|
||||
return models.ErrDashboardNotFound
|
||||
}
|
||||
|
||||
dashboard.SetId(dashboard.Id)
|
||||
@@ -262,7 +263,7 @@ func makeQueryResult(query *search.FindPersistedDashboardsQuery, res []Dashboard
|
||||
Uid: item.Uid,
|
||||
Title: item.Title,
|
||||
Uri: "db/" + item.Slug,
|
||||
Url: m.GetDashboardFolderUrl(item.IsFolder, item.Uid, item.Slug),
|
||||
Url: models.GetDashboardFolderUrl(item.IsFolder, item.Uid, item.Slug),
|
||||
Type: getHitType(item),
|
||||
FolderId: item.FolderId,
|
||||
FolderUid: item.FolderUid,
|
||||
@@ -271,7 +272,7 @@ func makeQueryResult(query *search.FindPersistedDashboardsQuery, res []Dashboard
|
||||
}
|
||||
|
||||
if item.FolderId > 0 {
|
||||
hit.FolderUrl = m.GetFolderUrl(item.FolderUid, item.FolderSlug)
|
||||
hit.FolderUrl = models.GetFolderUrl(item.FolderUid, item.FolderSlug)
|
||||
}
|
||||
|
||||
query.Result = append(query.Result, hit)
|
||||
@@ -283,7 +284,7 @@ func makeQueryResult(query *search.FindPersistedDashboardsQuery, res []Dashboard
|
||||
}
|
||||
}
|
||||
|
||||
func GetDashboardTags(query *m.GetDashboardTagsQuery) error {
|
||||
func GetDashboardTags(query *models.GetDashboardTagsQuery) error {
|
||||
sql := `SELECT
|
||||
COUNT(*) as count,
|
||||
term
|
||||
@@ -293,20 +294,20 @@ func GetDashboardTags(query *m.GetDashboardTagsQuery) error {
|
||||
GROUP BY term
|
||||
ORDER BY term`
|
||||
|
||||
query.Result = make([]*m.DashboardTagCloudItem, 0)
|
||||
query.Result = make([]*models.DashboardTagCloudItem, 0)
|
||||
sess := x.SQL(sql, query.OrgId)
|
||||
err := sess.Find(&query.Result)
|
||||
return err
|
||||
}
|
||||
|
||||
func DeleteDashboard(cmd *m.DeleteDashboardCommand) error {
|
||||
func DeleteDashboard(cmd *models.DeleteDashboardCommand) error {
|
||||
return inTransaction(func(sess *DBSession) error {
|
||||
dashboard := m.Dashboard{Id: cmd.Id, OrgId: cmd.OrgId}
|
||||
dashboard := models.Dashboard{Id: cmd.Id, OrgId: cmd.OrgId}
|
||||
has, err := sess.Get(&dashboard)
|
||||
if err != nil {
|
||||
return err
|
||||
} else if !has {
|
||||
return m.ErrDashboardNotFound
|
||||
return models.ErrDashboardNotFound
|
||||
}
|
||||
|
||||
deletes := []string{
|
||||
@@ -354,12 +355,12 @@ func DeleteDashboard(cmd *m.DeleteDashboardCommand) error {
|
||||
})
|
||||
}
|
||||
|
||||
func GetDashboards(query *m.GetDashboardsQuery) error {
|
||||
func GetDashboards(query *models.GetDashboardsQuery) error {
|
||||
if len(query.DashboardIds) == 0 {
|
||||
return m.ErrCommandValidationFailed
|
||||
return models.ErrCommandValidationFailed
|
||||
}
|
||||
|
||||
var dashboards = make([]*m.Dashboard, 0)
|
||||
var dashboards = make([]*models.Dashboard, 0)
|
||||
|
||||
err := x.In("id", query.DashboardIds).Find(&dashboards)
|
||||
query.Result = dashboards
|
||||
@@ -368,18 +369,18 @@ func GetDashboards(query *m.GetDashboardsQuery) error {
|
||||
|
||||
// GetDashboardPermissionsForUser returns the maximum permission the specified user has for a dashboard(s)
|
||||
// The function takes in a list of dashboard ids and the user id and role
|
||||
func GetDashboardPermissionsForUser(query *m.GetDashboardPermissionsForUserQuery) error {
|
||||
func GetDashboardPermissionsForUser(query *models.GetDashboardPermissionsForUserQuery) error {
|
||||
if len(query.DashboardIds) == 0 {
|
||||
return m.ErrCommandValidationFailed
|
||||
return models.ErrCommandValidationFailed
|
||||
}
|
||||
|
||||
if query.OrgRole == m.ROLE_ADMIN {
|
||||
var permissions = make([]*m.DashboardPermissionForUser, 0)
|
||||
if query.OrgRole == models.ROLE_ADMIN {
|
||||
var permissions = make([]*models.DashboardPermissionForUser, 0)
|
||||
for _, d := range query.DashboardIds {
|
||||
permissions = append(permissions, &m.DashboardPermissionForUser{
|
||||
permissions = append(permissions, &models.DashboardPermissionForUser{
|
||||
DashboardId: d,
|
||||
Permission: m.PERMISSION_ADMIN,
|
||||
PermissionName: m.PERMISSION_ADMIN.String(),
|
||||
Permission: models.PERMISSION_ADMIN,
|
||||
PermissionName: models.PERMISSION_ADMIN.String(),
|
||||
})
|
||||
}
|
||||
query.Result = permissions
|
||||
@@ -436,8 +437,8 @@ func GetDashboardPermissionsForUser(query *m.GetDashboardPermissionsForUserQuery
|
||||
return err
|
||||
}
|
||||
|
||||
func GetDashboardsByPluginId(query *m.GetDashboardsByPluginIdQuery) error {
|
||||
var dashboards = make([]*m.Dashboard, 0)
|
||||
func GetDashboardsByPluginId(query *models.GetDashboardsByPluginIdQuery) error {
|
||||
var dashboards = make([]*models.Dashboard, 0)
|
||||
whereExpr := "org_id=? AND plugin_id=? AND is_folder=" + dialect.BooleanStr(false)
|
||||
|
||||
err := x.Where(whereExpr, query.OrgId, query.PluginId).Find(&dashboards)
|
||||
@@ -449,7 +450,7 @@ type DashboardSlugDTO struct {
|
||||
Slug string
|
||||
}
|
||||
|
||||
func GetDashboardSlugById(query *m.GetDashboardSlugByIdQuery) error {
|
||||
func GetDashboardSlugById(query *models.GetDashboardSlugByIdQuery) error {
|
||||
var rawSql = `SELECT slug from dashboard WHERE Id=?`
|
||||
var slug = DashboardSlugDTO{}
|
||||
|
||||
@@ -458,15 +459,15 @@ func GetDashboardSlugById(query *m.GetDashboardSlugByIdQuery) error {
|
||||
if err != nil {
|
||||
return err
|
||||
} else if !exists {
|
||||
return m.ErrDashboardNotFound
|
||||
return models.ErrDashboardNotFound
|
||||
}
|
||||
|
||||
query.Result = slug.Slug
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetDashboardsBySlug(query *m.GetDashboardsBySlugQuery) error {
|
||||
var dashboards []*m.Dashboard
|
||||
func GetDashboardsBySlug(query *models.GetDashboardsBySlugQuery) error {
|
||||
var dashboards []*models.Dashboard
|
||||
|
||||
if err := x.Where("org_id=? AND slug=?", query.OrgId, query.Slug).Find(&dashboards); err != nil {
|
||||
return err
|
||||
@@ -476,28 +477,28 @@ func GetDashboardsBySlug(query *m.GetDashboardsBySlugQuery) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetDashboardUIDById(query *m.GetDashboardRefByIdQuery) error {
|
||||
func GetDashboardUIDById(query *models.GetDashboardRefByIdQuery) error {
|
||||
var rawSql = `SELECT uid, slug from dashboard WHERE Id=?`
|
||||
|
||||
us := &m.DashboardRef{}
|
||||
us := &models.DashboardRef{}
|
||||
|
||||
exists, err := x.SQL(rawSql, query.Id).Get(us)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
} else if !exists {
|
||||
return m.ErrDashboardNotFound
|
||||
return models.ErrDashboardNotFound
|
||||
}
|
||||
|
||||
query.Result = us
|
||||
return nil
|
||||
}
|
||||
|
||||
func getExistingDashboardByIdOrUidForUpdate(sess *DBSession, cmd *m.ValidateDashboardBeforeSaveCommand) (err error) {
|
||||
func getExistingDashboardByIdOrUidForUpdate(sess *DBSession, cmd *models.ValidateDashboardBeforeSaveCommand) (err error) {
|
||||
dash := cmd.Dashboard
|
||||
|
||||
dashWithIdExists := false
|
||||
var existingById m.Dashboard
|
||||
var existingById models.Dashboard
|
||||
|
||||
if dash.Id > 0 {
|
||||
dashWithIdExists, err = sess.Where("id=? AND org_id=?", dash.Id, dash.OrgId).Get(&existingById)
|
||||
@@ -506,7 +507,7 @@ func getExistingDashboardByIdOrUidForUpdate(sess *DBSession, cmd *m.ValidateDash
|
||||
}
|
||||
|
||||
if !dashWithIdExists {
|
||||
return m.ErrDashboardNotFound
|
||||
return models.ErrDashboardNotFound
|
||||
}
|
||||
|
||||
if dash.Uid == "" {
|
||||
@@ -515,7 +516,7 @@ func getExistingDashboardByIdOrUidForUpdate(sess *DBSession, cmd *m.ValidateDash
|
||||
}
|
||||
|
||||
dashWithUidExists := false
|
||||
var existingByUid m.Dashboard
|
||||
var existingByUid models.Dashboard
|
||||
|
||||
if dash.Uid != "" {
|
||||
dashWithUidExists, err = sess.Where("org_id=? AND uid=?", dash.OrgId, dash.Uid).Get(&existingByUid)
|
||||
@@ -525,14 +526,14 @@ func getExistingDashboardByIdOrUidForUpdate(sess *DBSession, cmd *m.ValidateDash
|
||||
}
|
||||
|
||||
if dash.FolderId > 0 {
|
||||
var existingFolder m.Dashboard
|
||||
var existingFolder models.Dashboard
|
||||
folderExists, folderErr := sess.Where("org_id=? AND id=? AND is_folder=?", dash.OrgId, dash.FolderId, dialect.BooleanStr(true)).Get(&existingFolder)
|
||||
if folderErr != nil {
|
||||
return folderErr
|
||||
}
|
||||
|
||||
if !folderExists {
|
||||
return m.ErrDashboardFolderNotFound
|
||||
return models.ErrDashboardFolderNotFound
|
||||
}
|
||||
}
|
||||
|
||||
@@ -541,7 +542,7 @@ func getExistingDashboardByIdOrUidForUpdate(sess *DBSession, cmd *m.ValidateDash
|
||||
}
|
||||
|
||||
if dashWithIdExists && dashWithUidExists && existingById.Id != existingByUid.Id {
|
||||
return m.ErrDashboardWithSameUIDExists
|
||||
return models.ErrDashboardWithSameUIDExists
|
||||
}
|
||||
|
||||
existing := existingById
|
||||
@@ -558,7 +559,7 @@ func getExistingDashboardByIdOrUidForUpdate(sess *DBSession, cmd *m.ValidateDash
|
||||
|
||||
if (existing.IsFolder && !dash.IsFolder) ||
|
||||
(!existing.IsFolder && dash.IsFolder) {
|
||||
return m.ErrDashboardTypeMismatch
|
||||
return models.ErrDashboardTypeMismatch
|
||||
}
|
||||
|
||||
if !dash.IsFolder && dash.FolderId != existing.FolderId {
|
||||
@@ -570,21 +571,21 @@ func getExistingDashboardByIdOrUidForUpdate(sess *DBSession, cmd *m.ValidateDash
|
||||
if cmd.Overwrite {
|
||||
dash.SetVersion(existing.Version)
|
||||
} else {
|
||||
return m.ErrDashboardVersionMismatch
|
||||
return models.ErrDashboardVersionMismatch
|
||||
}
|
||||
}
|
||||
|
||||
// do not allow plugin dashboard updates without overwrite flag
|
||||
if existing.PluginId != "" && !cmd.Overwrite {
|
||||
return m.UpdatePluginDashboardError{PluginId: existing.PluginId}
|
||||
return models.UpdatePluginDashboardError{PluginId: existing.PluginId}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func getExistingDashboardByTitleAndFolder(sess *DBSession, cmd *m.ValidateDashboardBeforeSaveCommand) error {
|
||||
func getExistingDashboardByTitleAndFolder(sess *DBSession, cmd *models.ValidateDashboardBeforeSaveCommand) error {
|
||||
dash := cmd.Dashboard
|
||||
var existing m.Dashboard
|
||||
var existing models.Dashboard
|
||||
|
||||
exists, err := sess.Where("org_id=? AND slug=? AND (is_folder=? OR folder_id=?)", dash.OrgId, dash.Slug, dialect.BooleanStr(true), dash.FolderId).Get(&existing)
|
||||
if err != nil {
|
||||
@@ -593,11 +594,11 @@ func getExistingDashboardByTitleAndFolder(sess *DBSession, cmd *m.ValidateDashbo
|
||||
|
||||
if exists && dash.Id != existing.Id {
|
||||
if existing.IsFolder && !dash.IsFolder {
|
||||
return m.ErrDashboardWithSameNameAsFolder
|
||||
return models.ErrDashboardWithSameNameAsFolder
|
||||
}
|
||||
|
||||
if !existing.IsFolder && dash.IsFolder {
|
||||
return m.ErrDashboardFolderWithSameNameAsDashboard
|
||||
return models.ErrDashboardFolderWithSameNameAsDashboard
|
||||
}
|
||||
|
||||
if !dash.IsFolder && (dash.FolderId != existing.FolderId || dash.Id == 0) {
|
||||
@@ -609,15 +610,15 @@ func getExistingDashboardByTitleAndFolder(sess *DBSession, cmd *m.ValidateDashbo
|
||||
dash.SetUid(existing.Uid)
|
||||
dash.SetVersion(existing.Version)
|
||||
} else {
|
||||
return m.ErrDashboardWithSameNameInFolderExists
|
||||
return models.ErrDashboardWithSameNameInFolderExists
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func ValidateDashboardBeforeSave(cmd *m.ValidateDashboardBeforeSaveCommand) (err error) {
|
||||
cmd.Result = &m.ValidateDashboardBeforeSaveResult{}
|
||||
func ValidateDashboardBeforeSave(cmd *models.ValidateDashboardBeforeSaveCommand) (err error) {
|
||||
cmd.Result = &models.ValidateDashboardBeforeSaveResult{}
|
||||
return inTransaction(func(sess *DBSession) error {
|
||||
if err = getExistingDashboardByIdOrUidForUpdate(sess, cmd); err != nil {
|
||||
return err
|
||||
@@ -631,15 +632,39 @@ func ValidateDashboardBeforeSave(cmd *m.ValidateDashboardBeforeSaveCommand) (err
|
||||
})
|
||||
}
|
||||
|
||||
func HasEditPermissionInFolders(query *m.HasEditPermissionInFoldersQuery) error {
|
||||
if query.SignedInUser.HasRole(m.ROLE_EDITOR) {
|
||||
func HasEditPermissionInFolders(query *models.HasEditPermissionInFoldersQuery) error {
|
||||
if query.SignedInUser.HasRole(models.ROLE_EDITOR) {
|
||||
query.Result = true
|
||||
return nil
|
||||
}
|
||||
|
||||
builder := &SqlBuilder{}
|
||||
builder.Write("SELECT COUNT(dashboard.id) AS count FROM dashboard WHERE dashboard.org_id = ? AND dashboard.is_folder = ?", query.SignedInUser.OrgId, dialect.BooleanStr(true))
|
||||
builder.writeDashboardPermissionFilter(query.SignedInUser, m.PERMISSION_EDIT)
|
||||
builder.writeDashboardPermissionFilter(query.SignedInUser, models.PERMISSION_EDIT)
|
||||
|
||||
type folderCount struct {
|
||||
Count int64
|
||||
}
|
||||
|
||||
resp := make([]*folderCount, 0)
|
||||
if err := x.SQL(builder.GetSqlString(), builder.params...).Find(&resp); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
query.Result = len(resp) > 0 && resp[0].Count > 0
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func HasAdminPermissionInFolders(query *models.HasAdminPermissionInFoldersQuery) error {
|
||||
if query.SignedInUser.HasRole(models.ROLE_ADMIN) {
|
||||
query.Result = true
|
||||
return nil
|
||||
}
|
||||
|
||||
builder := &SqlBuilder{}
|
||||
builder.Write("SELECT COUNT(dashboard.id) AS count FROM dashboard WHERE dashboard.org_id = ? AND dashboard.is_folder = ?", query.SignedInUser.OrgId, dialect.BooleanStr(true))
|
||||
builder.writeDashboardPermissionFilter(query.SignedInUser, models.PERMISSION_ADMIN)
|
||||
|
||||
type folderCount struct {
|
||||
Count int64
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
|
||||
m "github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/search"
|
||||
)
|
||||
|
||||
@@ -24,7 +24,7 @@ func TestDashboardFolderDataAccess(t *testing.T) {
|
||||
Convey("and no acls are set", func() {
|
||||
Convey("should return all dashboards", func() {
|
||||
query := &search.FindPersistedDashboardsQuery{
|
||||
SignedInUser: &m.SignedInUser{UserId: currentUser.Id, OrgId: 1, OrgRole: m.ROLE_VIEWER},
|
||||
SignedInUser: &models.SignedInUser{UserId: currentUser.Id, OrgId: 1, OrgRole: models.ROLE_VIEWER},
|
||||
OrgId: 1,
|
||||
DashboardIds: []int64{folder.Id, dashInRoot.Id},
|
||||
}
|
||||
@@ -38,11 +38,11 @@ func TestDashboardFolderDataAccess(t *testing.T) {
|
||||
|
||||
Convey("and acl is set for dashboard folder", func() {
|
||||
var otherUser int64 = 999
|
||||
testHelperUpdateDashboardAcl(folder.Id, m.DashboardAcl{DashboardId: folder.Id, OrgId: 1, UserId: otherUser, Permission: m.PERMISSION_EDIT})
|
||||
testHelperUpdateDashboardAcl(folder.Id, models.DashboardAcl{DashboardId: folder.Id, OrgId: 1, UserId: otherUser, Permission: models.PERMISSION_EDIT})
|
||||
|
||||
Convey("should not return folder", func() {
|
||||
query := &search.FindPersistedDashboardsQuery{
|
||||
SignedInUser: &m.SignedInUser{UserId: currentUser.Id, OrgId: 1, OrgRole: m.ROLE_VIEWER},
|
||||
SignedInUser: &models.SignedInUser{UserId: currentUser.Id, OrgId: 1, OrgRole: models.ROLE_VIEWER},
|
||||
OrgId: 1, DashboardIds: []int64{folder.Id, dashInRoot.Id},
|
||||
}
|
||||
err := SearchDashboards(query)
|
||||
@@ -53,11 +53,11 @@ func TestDashboardFolderDataAccess(t *testing.T) {
|
||||
})
|
||||
|
||||
Convey("when the user is given permission", func() {
|
||||
testHelperUpdateDashboardAcl(folder.Id, m.DashboardAcl{DashboardId: folder.Id, OrgId: 1, UserId: currentUser.Id, Permission: m.PERMISSION_EDIT})
|
||||
testHelperUpdateDashboardAcl(folder.Id, models.DashboardAcl{DashboardId: folder.Id, OrgId: 1, UserId: currentUser.Id, Permission: models.PERMISSION_EDIT})
|
||||
|
||||
Convey("should be able to access folder", func() {
|
||||
query := &search.FindPersistedDashboardsQuery{
|
||||
SignedInUser: &m.SignedInUser{UserId: currentUser.Id, OrgId: 1, OrgRole: m.ROLE_VIEWER},
|
||||
SignedInUser: &models.SignedInUser{UserId: currentUser.Id, OrgId: 1, OrgRole: models.ROLE_VIEWER},
|
||||
OrgId: 1,
|
||||
DashboardIds: []int64{folder.Id, dashInRoot.Id},
|
||||
}
|
||||
@@ -72,10 +72,10 @@ func TestDashboardFolderDataAccess(t *testing.T) {
|
||||
Convey("when the user is an admin", func() {
|
||||
Convey("should be able to access folder", func() {
|
||||
query := &search.FindPersistedDashboardsQuery{
|
||||
SignedInUser: &m.SignedInUser{
|
||||
SignedInUser: &models.SignedInUser{
|
||||
UserId: currentUser.Id,
|
||||
OrgId: 1,
|
||||
OrgRole: m.ROLE_ADMIN,
|
||||
OrgRole: models.ROLE_ADMIN,
|
||||
},
|
||||
OrgId: 1,
|
||||
DashboardIds: []int64{folder.Id, dashInRoot.Id},
|
||||
@@ -92,10 +92,10 @@ func TestDashboardFolderDataAccess(t *testing.T) {
|
||||
Convey("and acl is set for dashboard child and folder has all permissions removed", func() {
|
||||
var otherUser int64 = 999
|
||||
testHelperUpdateDashboardAcl(folder.Id)
|
||||
testHelperUpdateDashboardAcl(childDash.Id, m.DashboardAcl{DashboardId: folder.Id, OrgId: 1, UserId: otherUser, Permission: m.PERMISSION_EDIT})
|
||||
testHelperUpdateDashboardAcl(childDash.Id, models.DashboardAcl{DashboardId: folder.Id, OrgId: 1, UserId: otherUser, Permission: models.PERMISSION_EDIT})
|
||||
|
||||
Convey("should not return folder or child", func() {
|
||||
query := &search.FindPersistedDashboardsQuery{SignedInUser: &m.SignedInUser{UserId: currentUser.Id, OrgId: 1, OrgRole: m.ROLE_VIEWER}, OrgId: 1, DashboardIds: []int64{folder.Id, childDash.Id, dashInRoot.Id}}
|
||||
query := &search.FindPersistedDashboardsQuery{SignedInUser: &models.SignedInUser{UserId: currentUser.Id, OrgId: 1, OrgRole: models.ROLE_VIEWER}, OrgId: 1, DashboardIds: []int64{folder.Id, childDash.Id, dashInRoot.Id}}
|
||||
err := SearchDashboards(query)
|
||||
So(err, ShouldBeNil)
|
||||
So(len(query.Result), ShouldEqual, 1)
|
||||
@@ -103,10 +103,10 @@ func TestDashboardFolderDataAccess(t *testing.T) {
|
||||
})
|
||||
|
||||
Convey("when the user is given permission to child", func() {
|
||||
testHelperUpdateDashboardAcl(childDash.Id, m.DashboardAcl{DashboardId: childDash.Id, OrgId: 1, UserId: currentUser.Id, Permission: m.PERMISSION_EDIT})
|
||||
testHelperUpdateDashboardAcl(childDash.Id, models.DashboardAcl{DashboardId: childDash.Id, OrgId: 1, UserId: currentUser.Id, Permission: models.PERMISSION_EDIT})
|
||||
|
||||
Convey("should be able to search for child dashboard but not folder", func() {
|
||||
query := &search.FindPersistedDashboardsQuery{SignedInUser: &m.SignedInUser{UserId: currentUser.Id, OrgId: 1, OrgRole: m.ROLE_VIEWER}, OrgId: 1, DashboardIds: []int64{folder.Id, childDash.Id, dashInRoot.Id}}
|
||||
query := &search.FindPersistedDashboardsQuery{SignedInUser: &models.SignedInUser{UserId: currentUser.Id, OrgId: 1, OrgRole: models.ROLE_VIEWER}, OrgId: 1, DashboardIds: []int64{folder.Id, childDash.Id, dashInRoot.Id}}
|
||||
err := SearchDashboards(query)
|
||||
So(err, ShouldBeNil)
|
||||
So(len(query.Result), ShouldEqual, 2)
|
||||
@@ -118,10 +118,10 @@ func TestDashboardFolderDataAccess(t *testing.T) {
|
||||
Convey("when the user is an admin", func() {
|
||||
Convey("should be able to search for child dash and folder", func() {
|
||||
query := &search.FindPersistedDashboardsQuery{
|
||||
SignedInUser: &m.SignedInUser{
|
||||
SignedInUser: &models.SignedInUser{
|
||||
UserId: currentUser.Id,
|
||||
OrgId: 1,
|
||||
OrgRole: m.ROLE_ADMIN,
|
||||
OrgRole: models.ROLE_ADMIN,
|
||||
},
|
||||
OrgId: 1,
|
||||
DashboardIds: []int64{folder.Id, dashInRoot.Id, childDash.Id},
|
||||
@@ -149,7 +149,7 @@ func TestDashboardFolderDataAccess(t *testing.T) {
|
||||
|
||||
Convey("and one folder is expanded, the other collapsed", func() {
|
||||
Convey("should return dashboards in root and expanded folder", func() {
|
||||
query := &search.FindPersistedDashboardsQuery{FolderIds: []int64{rootFolderId, folder1.Id}, SignedInUser: &m.SignedInUser{UserId: currentUser.Id, OrgId: 1, OrgRole: m.ROLE_VIEWER}, OrgId: 1}
|
||||
query := &search.FindPersistedDashboardsQuery{FolderIds: []int64{rootFolderId, folder1.Id}, SignedInUser: &models.SignedInUser{UserId: currentUser.Id, OrgId: 1, OrgRole: models.ROLE_VIEWER}, OrgId: 1}
|
||||
err := SearchDashboards(query)
|
||||
So(err, ShouldBeNil)
|
||||
So(len(query.Result), ShouldEqual, 4)
|
||||
@@ -162,14 +162,14 @@ func TestDashboardFolderDataAccess(t *testing.T) {
|
||||
|
||||
Convey("and acl is set for one dashboard folder", func() {
|
||||
var otherUser int64 = 999
|
||||
testHelperUpdateDashboardAcl(folder1.Id, m.DashboardAcl{DashboardId: folder1.Id, OrgId: 1, UserId: otherUser, Permission: m.PERMISSION_EDIT})
|
||||
testHelperUpdateDashboardAcl(folder1.Id, models.DashboardAcl{DashboardId: folder1.Id, OrgId: 1, UserId: otherUser, Permission: models.PERMISSION_EDIT})
|
||||
|
||||
Convey("and a dashboard is moved from folder without acl to the folder with an acl", func() {
|
||||
moveDashboard(1, childDash2.Data, folder1.Id)
|
||||
|
||||
Convey("should not return folder with acl or its children", func() {
|
||||
query := &search.FindPersistedDashboardsQuery{
|
||||
SignedInUser: &m.SignedInUser{UserId: currentUser.Id, OrgId: 1, OrgRole: m.ROLE_VIEWER},
|
||||
SignedInUser: &models.SignedInUser{UserId: currentUser.Id, OrgId: 1, OrgRole: models.ROLE_VIEWER},
|
||||
OrgId: 1,
|
||||
DashboardIds: []int64{folder1.Id, childDash1.Id, childDash2.Id, dashInRoot.Id},
|
||||
}
|
||||
@@ -184,7 +184,7 @@ func TestDashboardFolderDataAccess(t *testing.T) {
|
||||
|
||||
Convey("should return folder without acl and its children", func() {
|
||||
query := &search.FindPersistedDashboardsQuery{
|
||||
SignedInUser: &m.SignedInUser{UserId: currentUser.Id, OrgId: 1, OrgRole: m.ROLE_VIEWER},
|
||||
SignedInUser: &models.SignedInUser{UserId: currentUser.Id, OrgId: 1, OrgRole: models.ROLE_VIEWER},
|
||||
OrgId: 1,
|
||||
DashboardIds: []int64{folder2.Id, childDash1.Id, childDash2.Id, dashInRoot.Id},
|
||||
}
|
||||
@@ -199,12 +199,12 @@ func TestDashboardFolderDataAccess(t *testing.T) {
|
||||
})
|
||||
|
||||
Convey("and a dashboard with an acl is moved to the folder without an acl", func() {
|
||||
testHelperUpdateDashboardAcl(childDash1.Id, m.DashboardAcl{DashboardId: childDash1.Id, OrgId: 1, UserId: otherUser, Permission: m.PERMISSION_EDIT})
|
||||
testHelperUpdateDashboardAcl(childDash1.Id, models.DashboardAcl{DashboardId: childDash1.Id, OrgId: 1, UserId: otherUser, Permission: models.PERMISSION_EDIT})
|
||||
moveDashboard(1, childDash1.Data, folder2.Id)
|
||||
|
||||
Convey("should return folder without acl but not the dashboard with acl", func() {
|
||||
query := &search.FindPersistedDashboardsQuery{
|
||||
SignedInUser: &m.SignedInUser{UserId: currentUser.Id, OrgId: 1, OrgRole: m.ROLE_VIEWER},
|
||||
SignedInUser: &models.SignedInUser{UserId: currentUser.Id, OrgId: 1, OrgRole: models.ROLE_VIEWER},
|
||||
OrgId: 1,
|
||||
DashboardIds: []int64{folder2.Id, childDash1.Id, childDash2.Id, dashInRoot.Id},
|
||||
}
|
||||
@@ -233,8 +233,8 @@ func TestDashboardFolderDataAccess(t *testing.T) {
|
||||
Convey("Should have write access to all dashboard folders in their org", func() {
|
||||
query := search.FindPersistedDashboardsQuery{
|
||||
OrgId: 1,
|
||||
SignedInUser: &m.SignedInUser{UserId: adminUser.Id, OrgRole: m.ROLE_ADMIN, OrgId: 1},
|
||||
Permission: m.PERMISSION_VIEW,
|
||||
SignedInUser: &models.SignedInUser{UserId: adminUser.Id, OrgRole: models.ROLE_ADMIN, OrgId: 1},
|
||||
Permission: models.PERMISSION_VIEW,
|
||||
Type: "dash-folder",
|
||||
}
|
||||
|
||||
@@ -247,11 +247,11 @@ func TestDashboardFolderDataAccess(t *testing.T) {
|
||||
})
|
||||
|
||||
Convey("should have write access to all folders and dashboards", func() {
|
||||
query := m.GetDashboardPermissionsForUserQuery{
|
||||
query := models.GetDashboardPermissionsForUserQuery{
|
||||
DashboardIds: []int64{folder1.Id, folder2.Id},
|
||||
OrgId: 1,
|
||||
UserId: adminUser.Id,
|
||||
OrgRole: m.ROLE_ADMIN,
|
||||
OrgRole: models.ROLE_ADMIN,
|
||||
}
|
||||
|
||||
err := GetDashboardPermissionsForUser(&query)
|
||||
@@ -259,26 +259,35 @@ func TestDashboardFolderDataAccess(t *testing.T) {
|
||||
|
||||
So(len(query.Result), ShouldEqual, 2)
|
||||
So(query.Result[0].DashboardId, ShouldEqual, folder1.Id)
|
||||
So(query.Result[0].Permission, ShouldEqual, m.PERMISSION_ADMIN)
|
||||
So(query.Result[0].Permission, ShouldEqual, models.PERMISSION_ADMIN)
|
||||
So(query.Result[1].DashboardId, ShouldEqual, folder2.Id)
|
||||
So(query.Result[1].Permission, ShouldEqual, m.PERMISSION_ADMIN)
|
||||
So(query.Result[1].Permission, ShouldEqual, models.PERMISSION_ADMIN)
|
||||
})
|
||||
|
||||
Convey("should have edit permission in folders", func() {
|
||||
query := &m.HasEditPermissionInFoldersQuery{
|
||||
SignedInUser: &m.SignedInUser{UserId: adminUser.Id, OrgId: 1, OrgRole: m.ROLE_ADMIN},
|
||||
query := &models.HasEditPermissionInFoldersQuery{
|
||||
SignedInUser: &models.SignedInUser{UserId: adminUser.Id, OrgId: 1, OrgRole: models.ROLE_ADMIN},
|
||||
}
|
||||
err := HasEditPermissionInFolders(query)
|
||||
So(err, ShouldBeNil)
|
||||
So(query.Result, ShouldBeTrue)
|
||||
})
|
||||
|
||||
Convey("should have admin permission in folders", func() {
|
||||
query := &models.HasAdminPermissionInFoldersQuery{
|
||||
SignedInUser: &models.SignedInUser{UserId: adminUser.Id, OrgId: 1, OrgRole: models.ROLE_ADMIN},
|
||||
}
|
||||
err := HasAdminPermissionInFolders(query)
|
||||
So(err, ShouldBeNil)
|
||||
So(query.Result, ShouldBeTrue)
|
||||
})
|
||||
})
|
||||
|
||||
Convey("Editor users", func() {
|
||||
query := search.FindPersistedDashboardsQuery{
|
||||
OrgId: 1,
|
||||
SignedInUser: &m.SignedInUser{UserId: editorUser.Id, OrgRole: m.ROLE_EDITOR, OrgId: 1},
|
||||
Permission: m.PERMISSION_EDIT,
|
||||
SignedInUser: &models.SignedInUser{UserId: editorUser.Id, OrgRole: models.ROLE_EDITOR, OrgId: 1},
|
||||
Permission: models.PERMISSION_EDIT,
|
||||
}
|
||||
|
||||
Convey("Should have write access to all dashboard folders with default ACL", func() {
|
||||
@@ -291,11 +300,11 @@ func TestDashboardFolderDataAccess(t *testing.T) {
|
||||
})
|
||||
|
||||
Convey("should have edit access to folders with default ACL", func() {
|
||||
query := m.GetDashboardPermissionsForUserQuery{
|
||||
query := models.GetDashboardPermissionsForUserQuery{
|
||||
DashboardIds: []int64{folder1.Id, folder2.Id},
|
||||
OrgId: 1,
|
||||
UserId: editorUser.Id,
|
||||
OrgRole: m.ROLE_EDITOR,
|
||||
OrgRole: models.ROLE_EDITOR,
|
||||
}
|
||||
|
||||
err := GetDashboardPermissionsForUser(&query)
|
||||
@@ -303,13 +312,13 @@ func TestDashboardFolderDataAccess(t *testing.T) {
|
||||
|
||||
So(len(query.Result), ShouldEqual, 2)
|
||||
So(query.Result[0].DashboardId, ShouldEqual, folder1.Id)
|
||||
So(query.Result[0].Permission, ShouldEqual, m.PERMISSION_EDIT)
|
||||
So(query.Result[0].Permission, ShouldEqual, models.PERMISSION_EDIT)
|
||||
So(query.Result[1].DashboardId, ShouldEqual, folder2.Id)
|
||||
So(query.Result[1].Permission, ShouldEqual, m.PERMISSION_EDIT)
|
||||
So(query.Result[1].Permission, ShouldEqual, models.PERMISSION_EDIT)
|
||||
})
|
||||
|
||||
Convey("Should have write access to one dashboard folder if default role changed to view for one folder", func() {
|
||||
testHelperUpdateDashboardAcl(folder1.Id, m.DashboardAcl{DashboardId: folder1.Id, OrgId: 1, UserId: editorUser.Id, Permission: m.PERMISSION_VIEW})
|
||||
testHelperUpdateDashboardAcl(folder1.Id, models.DashboardAcl{DashboardId: folder1.Id, OrgId: 1, UserId: editorUser.Id, Permission: models.PERMISSION_VIEW})
|
||||
|
||||
err := SearchDashboards(&query)
|
||||
So(err, ShouldBeNil)
|
||||
@@ -319,20 +328,29 @@ func TestDashboardFolderDataAccess(t *testing.T) {
|
||||
})
|
||||
|
||||
Convey("should have edit permission in folders", func() {
|
||||
query := &m.HasEditPermissionInFoldersQuery{
|
||||
SignedInUser: &m.SignedInUser{UserId: editorUser.Id, OrgId: 1, OrgRole: m.ROLE_EDITOR},
|
||||
query := &models.HasEditPermissionInFoldersQuery{
|
||||
SignedInUser: &models.SignedInUser{UserId: editorUser.Id, OrgId: 1, OrgRole: models.ROLE_EDITOR},
|
||||
}
|
||||
err := HasEditPermissionInFolders(query)
|
||||
So(err, ShouldBeNil)
|
||||
So(query.Result, ShouldBeTrue)
|
||||
})
|
||||
|
||||
Convey("should not have admin permission in folders", func() {
|
||||
query := &models.HasAdminPermissionInFoldersQuery{
|
||||
SignedInUser: &models.SignedInUser{UserId: adminUser.Id, OrgId: 1, OrgRole: models.ROLE_EDITOR},
|
||||
}
|
||||
err := HasAdminPermissionInFolders(query)
|
||||
So(err, ShouldBeNil)
|
||||
So(query.Result, ShouldBeFalse)
|
||||
})
|
||||
})
|
||||
|
||||
Convey("Viewer users", func() {
|
||||
query := search.FindPersistedDashboardsQuery{
|
||||
OrgId: 1,
|
||||
SignedInUser: &m.SignedInUser{UserId: viewerUser.Id, OrgRole: m.ROLE_VIEWER, OrgId: 1},
|
||||
Permission: m.PERMISSION_EDIT,
|
||||
SignedInUser: &models.SignedInUser{UserId: viewerUser.Id, OrgRole: models.ROLE_VIEWER, OrgId: 1},
|
||||
Permission: models.PERMISSION_EDIT,
|
||||
}
|
||||
|
||||
Convey("Should have no write access to any dashboard folders with default ACL", func() {
|
||||
@@ -343,11 +361,11 @@ func TestDashboardFolderDataAccess(t *testing.T) {
|
||||
})
|
||||
|
||||
Convey("should have view access to folders with default ACL", func() {
|
||||
query := m.GetDashboardPermissionsForUserQuery{
|
||||
query := models.GetDashboardPermissionsForUserQuery{
|
||||
DashboardIds: []int64{folder1.Id, folder2.Id},
|
||||
OrgId: 1,
|
||||
UserId: viewerUser.Id,
|
||||
OrgRole: m.ROLE_VIEWER,
|
||||
OrgRole: models.ROLE_VIEWER,
|
||||
}
|
||||
|
||||
err := GetDashboardPermissionsForUser(&query)
|
||||
@@ -355,13 +373,13 @@ func TestDashboardFolderDataAccess(t *testing.T) {
|
||||
|
||||
So(len(query.Result), ShouldEqual, 2)
|
||||
So(query.Result[0].DashboardId, ShouldEqual, folder1.Id)
|
||||
So(query.Result[0].Permission, ShouldEqual, m.PERMISSION_VIEW)
|
||||
So(query.Result[0].Permission, ShouldEqual, models.PERMISSION_VIEW)
|
||||
So(query.Result[1].DashboardId, ShouldEqual, folder2.Id)
|
||||
So(query.Result[1].Permission, ShouldEqual, m.PERMISSION_VIEW)
|
||||
So(query.Result[1].Permission, ShouldEqual, models.PERMISSION_VIEW)
|
||||
})
|
||||
|
||||
Convey("Should be able to get one dashboard folder if default role changed to edit for one folder", func() {
|
||||
testHelperUpdateDashboardAcl(folder1.Id, m.DashboardAcl{DashboardId: folder1.Id, OrgId: 1, UserId: viewerUser.Id, Permission: m.PERMISSION_EDIT})
|
||||
testHelperUpdateDashboardAcl(folder1.Id, models.DashboardAcl{DashboardId: folder1.Id, OrgId: 1, UserId: viewerUser.Id, Permission: models.PERMISSION_EDIT})
|
||||
|
||||
err := SearchDashboards(&query)
|
||||
So(err, ShouldBeNil)
|
||||
@@ -371,20 +389,29 @@ func TestDashboardFolderDataAccess(t *testing.T) {
|
||||
})
|
||||
|
||||
Convey("should not have edit permission in folders", func() {
|
||||
query := &m.HasEditPermissionInFoldersQuery{
|
||||
SignedInUser: &m.SignedInUser{UserId: viewerUser.Id, OrgId: 1, OrgRole: m.ROLE_VIEWER},
|
||||
query := &models.HasEditPermissionInFoldersQuery{
|
||||
SignedInUser: &models.SignedInUser{UserId: viewerUser.Id, OrgId: 1, OrgRole: models.ROLE_VIEWER},
|
||||
}
|
||||
err := HasEditPermissionInFolders(query)
|
||||
So(err, ShouldBeNil)
|
||||
So(query.Result, ShouldBeFalse)
|
||||
})
|
||||
|
||||
Convey("should not have admin permission in folders", func() {
|
||||
query := &models.HasAdminPermissionInFoldersQuery{
|
||||
SignedInUser: &models.SignedInUser{UserId: adminUser.Id, OrgId: 1, OrgRole: models.ROLE_VIEWER},
|
||||
}
|
||||
err := HasAdminPermissionInFolders(query)
|
||||
So(err, ShouldBeNil)
|
||||
So(query.Result, ShouldBeFalse)
|
||||
})
|
||||
|
||||
Convey("and admin permission is given for user with org role viewer in one dashboard folder", func() {
|
||||
testHelperUpdateDashboardAcl(folder1.Id, m.DashboardAcl{DashboardId: folder1.Id, OrgId: 1, UserId: viewerUser.Id, Permission: m.PERMISSION_ADMIN})
|
||||
testHelperUpdateDashboardAcl(folder1.Id, models.DashboardAcl{DashboardId: folder1.Id, OrgId: 1, UserId: viewerUser.Id, Permission: models.PERMISSION_ADMIN})
|
||||
|
||||
Convey("should have edit permission in folders", func() {
|
||||
query := &m.HasEditPermissionInFoldersQuery{
|
||||
SignedInUser: &m.SignedInUser{UserId: viewerUser.Id, OrgId: 1, OrgRole: m.ROLE_VIEWER},
|
||||
query := &models.HasEditPermissionInFoldersQuery{
|
||||
SignedInUser: &models.SignedInUser{UserId: viewerUser.Id, OrgId: 1, OrgRole: models.ROLE_VIEWER},
|
||||
}
|
||||
err := HasEditPermissionInFolders(query)
|
||||
So(err, ShouldBeNil)
|
||||
@@ -393,11 +420,11 @@ func TestDashboardFolderDataAccess(t *testing.T) {
|
||||
})
|
||||
|
||||
Convey("and edit permission is given for user with org role viewer in one dashboard folder", func() {
|
||||
testHelperUpdateDashboardAcl(folder1.Id, m.DashboardAcl{DashboardId: folder1.Id, OrgId: 1, UserId: viewerUser.Id, Permission: m.PERMISSION_EDIT})
|
||||
testHelperUpdateDashboardAcl(folder1.Id, models.DashboardAcl{DashboardId: folder1.Id, OrgId: 1, UserId: viewerUser.Id, Permission: models.PERMISSION_EDIT})
|
||||
|
||||
Convey("should have edit permission in folders", func() {
|
||||
query := &m.HasEditPermissionInFoldersQuery{
|
||||
SignedInUser: &m.SignedInUser{UserId: viewerUser.Id, OrgId: 1, OrgRole: m.ROLE_VIEWER},
|
||||
query := &models.HasEditPermissionInFoldersQuery{
|
||||
SignedInUser: &models.SignedInUser{UserId: viewerUser.Id, OrgId: 1, OrgRole: models.ROLE_VIEWER},
|
||||
}
|
||||
err := HasEditPermissionInFolders(query)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
|
||||
m "github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
)
|
||||
|
||||
type Test struct {
|
||||
@@ -17,11 +17,11 @@ func TestDataAccess(t *testing.T) {
|
||||
Convey("Testing DB", t, func() {
|
||||
InitTestDB(t)
|
||||
Convey("Can add datasource", func() {
|
||||
err := AddDataSource(&m.AddDataSourceCommand{
|
||||
err := AddDataSource(&models.AddDataSourceCommand{
|
||||
OrgId: 10,
|
||||
Name: "laban",
|
||||
Type: m.DS_INFLUXDB,
|
||||
Access: m.DS_ACCESS_DIRECT,
|
||||
Type: models.DS_INFLUXDB,
|
||||
Access: models.DS_ACCESS_DIRECT,
|
||||
Url: "http://test",
|
||||
Database: "site",
|
||||
ReadOnly: true,
|
||||
@@ -29,7 +29,7 @@ func TestDataAccess(t *testing.T) {
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
query := m.GetDataSourcesQuery{OrgId: 10}
|
||||
query := models.GetDataSourcesQuery{OrgId: 10}
|
||||
err = GetDataSources(&query)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
@@ -43,28 +43,28 @@ func TestDataAccess(t *testing.T) {
|
||||
})
|
||||
|
||||
Convey("Given a datasource", func() {
|
||||
err := AddDataSource(&m.AddDataSourceCommand{
|
||||
err := AddDataSource(&models.AddDataSourceCommand{
|
||||
OrgId: 10,
|
||||
Name: "nisse",
|
||||
Type: m.DS_GRAPHITE,
|
||||
Access: m.DS_ACCESS_DIRECT,
|
||||
Type: models.DS_GRAPHITE,
|
||||
Access: models.DS_ACCESS_DIRECT,
|
||||
Url: "http://test",
|
||||
})
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
query := m.GetDataSourcesQuery{OrgId: 10}
|
||||
query := models.GetDataSourcesQuery{OrgId: 10}
|
||||
err = GetDataSources(&query)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
ds := query.Result[0]
|
||||
|
||||
Convey(" updated ", func() {
|
||||
cmd := &m.UpdateDataSourceCommand{
|
||||
cmd := &models.UpdateDataSourceCommand{
|
||||
Id: ds.Id,
|
||||
OrgId: 10,
|
||||
Name: "nisse",
|
||||
Type: m.DS_GRAPHITE,
|
||||
Access: m.DS_ACCESS_PROXY,
|
||||
Type: models.DS_GRAPHITE,
|
||||
Access: models.DS_ACCESS_PROXY,
|
||||
Url: "http://test",
|
||||
Version: ds.Version,
|
||||
}
|
||||
@@ -75,27 +75,27 @@ func TestDataAccess(t *testing.T) {
|
||||
})
|
||||
|
||||
Convey("when someone else updated between read and update", func() {
|
||||
query := m.GetDataSourcesQuery{OrgId: 10}
|
||||
query := models.GetDataSourcesQuery{OrgId: 10}
|
||||
err = GetDataSources(&query)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
ds := query.Result[0]
|
||||
intendedUpdate := &m.UpdateDataSourceCommand{
|
||||
intendedUpdate := &models.UpdateDataSourceCommand{
|
||||
Id: ds.Id,
|
||||
OrgId: 10,
|
||||
Name: "nisse",
|
||||
Type: m.DS_GRAPHITE,
|
||||
Access: m.DS_ACCESS_PROXY,
|
||||
Type: models.DS_GRAPHITE,
|
||||
Access: models.DS_ACCESS_PROXY,
|
||||
Url: "http://test",
|
||||
Version: ds.Version,
|
||||
}
|
||||
|
||||
updateFromOtherUser := &m.UpdateDataSourceCommand{
|
||||
updateFromOtherUser := &models.UpdateDataSourceCommand{
|
||||
Id: ds.Id,
|
||||
OrgId: 10,
|
||||
Name: "nisse",
|
||||
Type: m.DS_GRAPHITE,
|
||||
Access: m.DS_ACCESS_PROXY,
|
||||
Type: models.DS_GRAPHITE,
|
||||
Access: models.DS_ACCESS_PROXY,
|
||||
Url: "http://test",
|
||||
Version: ds.Version,
|
||||
}
|
||||
@@ -108,12 +108,12 @@ func TestDataAccess(t *testing.T) {
|
||||
})
|
||||
|
||||
Convey("updating datasource without version", func() {
|
||||
cmd := &m.UpdateDataSourceCommand{
|
||||
cmd := &models.UpdateDataSourceCommand{
|
||||
Id: ds.Id,
|
||||
OrgId: 10,
|
||||
Name: "nisse",
|
||||
Type: m.DS_GRAPHITE,
|
||||
Access: m.DS_ACCESS_PROXY,
|
||||
Type: models.DS_GRAPHITE,
|
||||
Access: models.DS_ACCESS_PROXY,
|
||||
Url: "http://test",
|
||||
}
|
||||
|
||||
@@ -124,12 +124,12 @@ func TestDataAccess(t *testing.T) {
|
||||
})
|
||||
|
||||
Convey("updating datasource without higher version", func() {
|
||||
cmd := &m.UpdateDataSourceCommand{
|
||||
cmd := &models.UpdateDataSourceCommand{
|
||||
Id: ds.Id,
|
||||
OrgId: 10,
|
||||
Name: "nisse",
|
||||
Type: m.DS_GRAPHITE,
|
||||
Access: m.DS_ACCESS_PROXY,
|
||||
Type: models.DS_GRAPHITE,
|
||||
Access: models.DS_ACCESS_PROXY,
|
||||
Url: "http://test",
|
||||
Version: 90000,
|
||||
}
|
||||
@@ -142,7 +142,7 @@ func TestDataAccess(t *testing.T) {
|
||||
})
|
||||
|
||||
Convey("Can delete datasource by id", func() {
|
||||
err := DeleteDataSourceById(&m.DeleteDataSourceByIdCommand{Id: ds.Id, OrgId: ds.OrgId})
|
||||
err := DeleteDataSourceById(&models.DeleteDataSourceByIdCommand{Id: ds.Id, OrgId: ds.OrgId})
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
GetDataSources(&query)
|
||||
@@ -150,7 +150,7 @@ func TestDataAccess(t *testing.T) {
|
||||
})
|
||||
|
||||
Convey("Can delete datasource by name", func() {
|
||||
err := DeleteDataSourceByName(&m.DeleteDataSourceByNameCommand{Name: ds.Name, OrgId: ds.OrgId})
|
||||
err := DeleteDataSourceByName(&models.DeleteDataSourceByNameCommand{Name: ds.Name, OrgId: ds.OrgId})
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
GetDataSources(&query)
|
||||
@@ -158,7 +158,7 @@ func TestDataAccess(t *testing.T) {
|
||||
})
|
||||
|
||||
Convey("Can not delete datasource with wrong orgId", func() {
|
||||
err := DeleteDataSourceById(&m.DeleteDataSourceByIdCommand{Id: ds.Id, OrgId: 123123})
|
||||
err := DeleteDataSourceById(&models.DeleteDataSourceByIdCommand{Id: ds.Id, OrgId: 123123})
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
GetDataSources(&query)
|
||||
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
m "github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -21,6 +21,7 @@ func init() {
|
||||
bus.AddHandler("sql", UpdateTeamMember)
|
||||
bus.AddHandler("sql", RemoveTeamMember)
|
||||
bus.AddHandler("sql", GetTeamMembers)
|
||||
bus.AddHandler("sql", IsAdminOfTeams)
|
||||
}
|
||||
|
||||
func getTeamSearchSqlBase() string {
|
||||
@@ -45,16 +46,16 @@ func getTeamSelectSqlBase() string {
|
||||
FROM team as team `
|
||||
}
|
||||
|
||||
func CreateTeam(cmd *m.CreateTeamCommand) error {
|
||||
func CreateTeam(cmd *models.CreateTeamCommand) error {
|
||||
return inTransaction(func(sess *DBSession) error {
|
||||
|
||||
if isNameTaken, err := isTeamNameTaken(cmd.OrgId, cmd.Name, 0, sess); err != nil {
|
||||
return err
|
||||
} else if isNameTaken {
|
||||
return m.ErrTeamNameTaken
|
||||
return models.ErrTeamNameTaken
|
||||
}
|
||||
|
||||
team := m.Team{
|
||||
team := models.Team{
|
||||
Name: cmd.Name,
|
||||
Email: cmd.Email,
|
||||
OrgId: cmd.OrgId,
|
||||
@@ -70,16 +71,16 @@ func CreateTeam(cmd *m.CreateTeamCommand) error {
|
||||
})
|
||||
}
|
||||
|
||||
func UpdateTeam(cmd *m.UpdateTeamCommand) error {
|
||||
func UpdateTeam(cmd *models.UpdateTeamCommand) error {
|
||||
return inTransaction(func(sess *DBSession) error {
|
||||
|
||||
if isNameTaken, err := isTeamNameTaken(cmd.OrgId, cmd.Name, cmd.Id, sess); err != nil {
|
||||
return err
|
||||
} else if isNameTaken {
|
||||
return m.ErrTeamNameTaken
|
||||
return models.ErrTeamNameTaken
|
||||
}
|
||||
|
||||
team := m.Team{
|
||||
team := models.Team{
|
||||
Name: cmd.Name,
|
||||
Email: cmd.Email,
|
||||
Updated: time.Now(),
|
||||
@@ -94,7 +95,7 @@ func UpdateTeam(cmd *m.UpdateTeamCommand) error {
|
||||
}
|
||||
|
||||
if affectedRows == 0 {
|
||||
return m.ErrTeamNotFound
|
||||
return models.ErrTeamNotFound
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -102,7 +103,7 @@ func UpdateTeam(cmd *m.UpdateTeamCommand) error {
|
||||
}
|
||||
|
||||
// DeleteTeam will delete a team, its member and any permissions connected to the team
|
||||
func DeleteTeam(cmd *m.DeleteTeamCommand) error {
|
||||
func DeleteTeam(cmd *models.DeleteTeamCommand) error {
|
||||
return inTransaction(func(sess *DBSession) error {
|
||||
if _, err := teamExists(cmd.OrgId, cmd.Id, sess); err != nil {
|
||||
return err
|
||||
@@ -128,14 +129,14 @@ func teamExists(orgId int64, teamId int64, sess *DBSession) (bool, error) {
|
||||
if res, err := sess.Query("SELECT 1 from team WHERE org_id=? and id=?", orgId, teamId); err != nil {
|
||||
return false, err
|
||||
} else if len(res) != 1 {
|
||||
return false, m.ErrTeamNotFound
|
||||
return false, models.ErrTeamNotFound
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func isTeamNameTaken(orgId int64, name string, existingId int64, sess *DBSession) (bool, error) {
|
||||
var team m.Team
|
||||
var team models.Team
|
||||
exists, err := sess.Where("org_id=? and name=?", orgId, name).Get(&team)
|
||||
|
||||
if err != nil {
|
||||
@@ -149,9 +150,9 @@ func isTeamNameTaken(orgId int64, name string, existingId int64, sess *DBSession
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func SearchTeams(query *m.SearchTeamsQuery) error {
|
||||
query.Result = m.SearchTeamQueryResult{
|
||||
Teams: make([]*m.TeamDTO, 0),
|
||||
func SearchTeams(query *models.SearchTeamsQuery) error {
|
||||
query.Result = models.SearchTeamQueryResult{
|
||||
Teams: make([]*models.TeamDTO, 0),
|
||||
}
|
||||
queryWithWildcards := "%" + query.Query + "%"
|
||||
|
||||
@@ -189,7 +190,7 @@ func SearchTeams(query *m.SearchTeamsQuery) error {
|
||||
return err
|
||||
}
|
||||
|
||||
team := m.Team{}
|
||||
team := models.Team{}
|
||||
countSess := x.Table("team")
|
||||
if query.Query != "" {
|
||||
countSess.Where(`name `+dialect.LikeStr()+` ?`, queryWithWildcards)
|
||||
@@ -205,13 +206,13 @@ func SearchTeams(query *m.SearchTeamsQuery) error {
|
||||
return err
|
||||
}
|
||||
|
||||
func GetTeamById(query *m.GetTeamByIdQuery) error {
|
||||
func GetTeamById(query *models.GetTeamByIdQuery) error {
|
||||
var sql bytes.Buffer
|
||||
|
||||
sql.WriteString(getTeamSelectSqlBase())
|
||||
sql.WriteString(` WHERE team.org_id = ? and team.id = ?`)
|
||||
|
||||
var team m.TeamDTO
|
||||
var team models.TeamDTO
|
||||
exists, err := x.SQL(sql.String(), query.OrgId, query.Id).Get(&team)
|
||||
|
||||
if err != nil {
|
||||
@@ -219,7 +220,7 @@ func GetTeamById(query *m.GetTeamByIdQuery) error {
|
||||
}
|
||||
|
||||
if !exists {
|
||||
return m.ErrTeamNotFound
|
||||
return models.ErrTeamNotFound
|
||||
}
|
||||
|
||||
query.Result = &team
|
||||
@@ -227,8 +228,8 @@ func GetTeamById(query *m.GetTeamByIdQuery) error {
|
||||
}
|
||||
|
||||
// GetTeamsByUser is used by the Guardian when checking a users' permissions
|
||||
func GetTeamsByUser(query *m.GetTeamsByUserQuery) error {
|
||||
query.Result = make([]*m.TeamDTO, 0)
|
||||
func GetTeamsByUser(query *models.GetTeamsByUserQuery) error {
|
||||
query.Result = make([]*models.TeamDTO, 0)
|
||||
|
||||
var sql bytes.Buffer
|
||||
|
||||
@@ -241,19 +242,19 @@ func GetTeamsByUser(query *m.GetTeamsByUserQuery) error {
|
||||
}
|
||||
|
||||
// AddTeamMember adds a user to a team
|
||||
func AddTeamMember(cmd *m.AddTeamMemberCommand) error {
|
||||
func AddTeamMember(cmd *models.AddTeamMemberCommand) error {
|
||||
return inTransaction(func(sess *DBSession) error {
|
||||
if res, err := sess.Query("SELECT 1 from team_member WHERE org_id=? and team_id=? and user_id=?", cmd.OrgId, cmd.TeamId, cmd.UserId); err != nil {
|
||||
return err
|
||||
} else if len(res) == 1 {
|
||||
return m.ErrTeamMemberAlreadyAdded
|
||||
return models.ErrTeamMemberAlreadyAdded
|
||||
}
|
||||
|
||||
if _, err := teamExists(cmd.OrgId, cmd.TeamId, sess); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
entity := m.TeamMember{
|
||||
entity := models.TeamMember{
|
||||
OrgId: cmd.OrgId,
|
||||
TeamId: cmd.TeamId,
|
||||
UserId: cmd.UserId,
|
||||
@@ -268,23 +269,23 @@ func AddTeamMember(cmd *m.AddTeamMemberCommand) error {
|
||||
})
|
||||
}
|
||||
|
||||
func getTeamMember(sess *DBSession, orgId int64, teamId int64, userId int64) (m.TeamMember, error) {
|
||||
func getTeamMember(sess *DBSession, orgId int64, teamId int64, userId int64) (models.TeamMember, error) {
|
||||
rawSql := `SELECT * FROM team_member WHERE org_id=? and team_id=? and user_id=?`
|
||||
var member m.TeamMember
|
||||
var member models.TeamMember
|
||||
exists, err := sess.SQL(rawSql, orgId, teamId, userId).Get(&member)
|
||||
|
||||
if err != nil {
|
||||
return member, err
|
||||
}
|
||||
if !exists {
|
||||
return member, m.ErrTeamMemberNotFound
|
||||
return member, models.ErrTeamMemberNotFound
|
||||
}
|
||||
|
||||
return member, nil
|
||||
}
|
||||
|
||||
// UpdateTeamMember updates a team member
|
||||
func UpdateTeamMember(cmd *m.UpdateTeamMemberCommand) error {
|
||||
func UpdateTeamMember(cmd *models.UpdateTeamMemberCommand) error {
|
||||
return inTransaction(func(sess *DBSession) error {
|
||||
member, err := getTeamMember(sess, cmd.OrgId, cmd.TeamId, cmd.UserId)
|
||||
if err != nil {
|
||||
@@ -298,7 +299,7 @@ func UpdateTeamMember(cmd *m.UpdateTeamMemberCommand) error {
|
||||
}
|
||||
}
|
||||
|
||||
if cmd.Permission != m.PERMISSION_ADMIN { // make sure we don't get invalid permission levels in store
|
||||
if cmd.Permission != models.PERMISSION_ADMIN { // make sure we don't get invalid permission levels in store
|
||||
cmd.Permission = 0
|
||||
}
|
||||
|
||||
@@ -310,7 +311,7 @@ func UpdateTeamMember(cmd *m.UpdateTeamMemberCommand) error {
|
||||
}
|
||||
|
||||
// RemoveTeamMember removes a member from a team
|
||||
func RemoveTeamMember(cmd *m.RemoveTeamMemberCommand) error {
|
||||
func RemoveTeamMember(cmd *models.RemoveTeamMemberCommand) error {
|
||||
return inTransaction(func(sess *DBSession) error {
|
||||
if _, err := teamExists(cmd.OrgId, cmd.TeamId, sess); err != nil {
|
||||
return err
|
||||
@@ -330,7 +331,7 @@ func RemoveTeamMember(cmd *m.RemoveTeamMemberCommand) error {
|
||||
}
|
||||
rows, err := res.RowsAffected()
|
||||
if rows == 0 {
|
||||
return m.ErrTeamMemberNotFound
|
||||
return models.ErrTeamMemberNotFound
|
||||
}
|
||||
|
||||
return err
|
||||
@@ -340,7 +341,7 @@ func RemoveTeamMember(cmd *m.RemoveTeamMemberCommand) error {
|
||||
func isLastAdmin(sess *DBSession, orgId int64, teamId int64, userId int64) (bool, error) {
|
||||
rawSql := "SELECT user_id FROM team_member WHERE org_id=? and team_id=? and permission=?"
|
||||
userIds := []*int64{}
|
||||
err := sess.SQL(rawSql, orgId, teamId, m.PERMISSION_ADMIN).Find(&userIds)
|
||||
err := sess.SQL(rawSql, orgId, teamId, models.PERMISSION_ADMIN).Find(&userIds)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@@ -354,15 +355,15 @@ func isLastAdmin(sess *DBSession, orgId int64, teamId int64, userId int64) (bool
|
||||
}
|
||||
|
||||
if isAdmin && len(userIds) == 1 {
|
||||
return true, m.ErrLastTeamAdmin
|
||||
return true, models.ErrLastTeamAdmin
|
||||
}
|
||||
|
||||
return false, err
|
||||
}
|
||||
|
||||
// GetTeamMembers return a list of members for the specified team
|
||||
func GetTeamMembers(query *m.GetTeamMembersQuery) error {
|
||||
query.Result = make([]*m.TeamMemberDTO, 0)
|
||||
func GetTeamMembers(query *models.GetTeamMembersQuery) error {
|
||||
query.Result = make([]*models.TeamMemberDTO, 0)
|
||||
sess := x.Table("team_member")
|
||||
sess.Join("INNER", x.Dialect().Quote("user"), fmt.Sprintf("team_member.user_id=%s.id", x.Dialect().Quote("user")))
|
||||
|
||||
@@ -392,3 +393,21 @@ func GetTeamMembers(query *m.GetTeamMembersQuery) error {
|
||||
err := sess.Find(&query.Result)
|
||||
return err
|
||||
}
|
||||
|
||||
func IsAdminOfTeams(query *models.IsAdminOfTeamsQuery) error {
|
||||
builder := &SqlBuilder{}
|
||||
builder.Write("SELECT COUNT(team.id) AS count FROM team INNER JOIN team_member ON team_member.team_id = team.id WHERE team.org_id = ? AND team_member.user_id = ? AND team_member.permission = ?", query.SignedInUser.OrgId, query.SignedInUser.UserId, models.PERMISSION_ADMIN)
|
||||
|
||||
type teamCount struct {
|
||||
Count int64
|
||||
}
|
||||
|
||||
resp := make([]*teamCount, 0)
|
||||
if err := x.SQL(builder.GetSqlString(), builder.params...).Find(&resp); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
query.Result = len(resp) > 0 && resp[0].Count > 0
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
|
||||
m "github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
)
|
||||
|
||||
func TestTeamCommandsAndQueries(t *testing.T) {
|
||||
@@ -18,7 +18,7 @@ func TestTeamCommandsAndQueries(t *testing.T) {
|
||||
Convey("Given saved users and two teams", func() {
|
||||
var userIds []int64
|
||||
for i := 0; i < 5; i++ {
|
||||
userCmd := &m.CreateUserCommand{
|
||||
userCmd := &models.CreateUserCommand{
|
||||
Email: fmt.Sprint("user", i, "@test.com"),
|
||||
Name: fmt.Sprint("user", i),
|
||||
Login: fmt.Sprint("loginuser", i),
|
||||
@@ -29,8 +29,8 @@ func TestTeamCommandsAndQueries(t *testing.T) {
|
||||
}
|
||||
|
||||
var testOrgId int64 = 1
|
||||
group1 := m.CreateTeamCommand{OrgId: testOrgId, Name: "group1 name", Email: "test1@test.com"}
|
||||
group2 := m.CreateTeamCommand{OrgId: testOrgId, Name: "group2 name", Email: "test2@test.com"}
|
||||
group1 := models.CreateTeamCommand{OrgId: testOrgId, Name: "group1 name", Email: "test1@test.com"}
|
||||
group2 := models.CreateTeamCommand{OrgId: testOrgId, Name: "group2 name", Email: "test2@test.com"}
|
||||
|
||||
err := CreateTeam(&group1)
|
||||
So(err, ShouldBeNil)
|
||||
@@ -38,7 +38,7 @@ func TestTeamCommandsAndQueries(t *testing.T) {
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
Convey("Should be able to create teams and add users", func() {
|
||||
query := &m.SearchTeamsQuery{OrgId: testOrgId, Name: "group1 name", Page: 1, Limit: 10}
|
||||
query := &models.SearchTeamsQuery{OrgId: testOrgId, Name: "group1 name", Page: 1, Limit: 10}
|
||||
err = SearchTeams(query)
|
||||
So(err, ShouldBeNil)
|
||||
So(query.Page, ShouldEqual, 1)
|
||||
@@ -48,12 +48,12 @@ func TestTeamCommandsAndQueries(t *testing.T) {
|
||||
So(team1.Email, ShouldEqual, "test1@test.com")
|
||||
So(team1.OrgId, ShouldEqual, testOrgId)
|
||||
|
||||
err = AddTeamMember(&m.AddTeamMemberCommand{OrgId: testOrgId, TeamId: team1.Id, UserId: userIds[0]})
|
||||
err = AddTeamMember(&models.AddTeamMemberCommand{OrgId: testOrgId, TeamId: team1.Id, UserId: userIds[0]})
|
||||
So(err, ShouldBeNil)
|
||||
err = AddTeamMember(&m.AddTeamMemberCommand{OrgId: testOrgId, TeamId: team1.Id, UserId: userIds[1], External: true})
|
||||
err = AddTeamMember(&models.AddTeamMemberCommand{OrgId: testOrgId, TeamId: team1.Id, UserId: userIds[1], External: true})
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
q1 := &m.GetTeamMembersQuery{OrgId: testOrgId, TeamId: team1.Id}
|
||||
q1 := &models.GetTeamMembersQuery{OrgId: testOrgId, TeamId: team1.Id}
|
||||
err = GetTeamMembers(q1)
|
||||
So(err, ShouldBeNil)
|
||||
So(q1.Result, ShouldHaveLength, 2)
|
||||
@@ -65,7 +65,7 @@ func TestTeamCommandsAndQueries(t *testing.T) {
|
||||
So(q1.Result[1].OrgId, ShouldEqual, testOrgId)
|
||||
So(q1.Result[1].External, ShouldEqual, true)
|
||||
|
||||
q2 := &m.GetTeamMembersQuery{OrgId: testOrgId, TeamId: team1.Id, External: true}
|
||||
q2 := &models.GetTeamMembersQuery{OrgId: testOrgId, TeamId: team1.Id, External: true}
|
||||
err = GetTeamMembers(q2)
|
||||
So(err, ShouldBeNil)
|
||||
So(q2.Result, ShouldHaveLength, 1)
|
||||
@@ -77,20 +77,20 @@ func TestTeamCommandsAndQueries(t *testing.T) {
|
||||
|
||||
Convey("Should return latest auth module for users when getting team members", func() {
|
||||
userId := userIds[1]
|
||||
err := SetAuthInfo(&m.SetAuthInfoCommand{UserId: userId, AuthModule: "oauth_github", AuthId: "1234567"})
|
||||
err := SetAuthInfo(&models.SetAuthInfoCommand{UserId: userId, AuthModule: "oauth_github", AuthId: "1234567"})
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
teamQuery := &m.SearchTeamsQuery{OrgId: testOrgId, Name: "group1 name", Page: 1, Limit: 10}
|
||||
teamQuery := &models.SearchTeamsQuery{OrgId: testOrgId, Name: "group1 name", Page: 1, Limit: 10}
|
||||
err = SearchTeams(teamQuery)
|
||||
So(err, ShouldBeNil)
|
||||
So(teamQuery.Page, ShouldEqual, 1)
|
||||
|
||||
team1 := teamQuery.Result.Teams[0]
|
||||
|
||||
err = AddTeamMember(&m.AddTeamMemberCommand{OrgId: testOrgId, TeamId: team1.Id, UserId: userId, External: true})
|
||||
err = AddTeamMember(&models.AddTeamMemberCommand{OrgId: testOrgId, TeamId: team1.Id, UserId: userId, External: true})
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
memberQuery := &m.GetTeamMembersQuery{OrgId: testOrgId, TeamId: team1.Id, External: true}
|
||||
memberQuery := &models.GetTeamMembersQuery{OrgId: testOrgId, TeamId: team1.Id, External: true}
|
||||
err = GetTeamMembers(memberQuery)
|
||||
So(err, ShouldBeNil)
|
||||
So(memberQuery.Result, ShouldHaveLength, 1)
|
||||
@@ -104,44 +104,44 @@ func TestTeamCommandsAndQueries(t *testing.T) {
|
||||
Convey("Should be able to update users in a team", func() {
|
||||
userId := userIds[0]
|
||||
team := group1.Result
|
||||
addMemberCmd := m.AddTeamMemberCommand{OrgId: testOrgId, TeamId: team.Id, UserId: userId}
|
||||
addMemberCmd := models.AddTeamMemberCommand{OrgId: testOrgId, TeamId: team.Id, UserId: userId}
|
||||
err = AddTeamMember(&addMemberCmd)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
qBeforeUpdate := &m.GetTeamMembersQuery{OrgId: testOrgId, TeamId: team.Id}
|
||||
qBeforeUpdate := &models.GetTeamMembersQuery{OrgId: testOrgId, TeamId: team.Id}
|
||||
err = GetTeamMembers(qBeforeUpdate)
|
||||
So(err, ShouldBeNil)
|
||||
So(qBeforeUpdate.Result[0].Permission, ShouldEqual, 0)
|
||||
|
||||
err = UpdateTeamMember(&m.UpdateTeamMemberCommand{
|
||||
err = UpdateTeamMember(&models.UpdateTeamMemberCommand{
|
||||
UserId: userId,
|
||||
OrgId: testOrgId,
|
||||
TeamId: team.Id,
|
||||
Permission: m.PERMISSION_ADMIN,
|
||||
Permission: models.PERMISSION_ADMIN,
|
||||
})
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
qAfterUpdate := &m.GetTeamMembersQuery{OrgId: testOrgId, TeamId: team.Id}
|
||||
qAfterUpdate := &models.GetTeamMembersQuery{OrgId: testOrgId, TeamId: team.Id}
|
||||
err = GetTeamMembers(qAfterUpdate)
|
||||
So(err, ShouldBeNil)
|
||||
So(qAfterUpdate.Result[0].Permission, ShouldEqual, m.PERMISSION_ADMIN)
|
||||
So(qAfterUpdate.Result[0].Permission, ShouldEqual, models.PERMISSION_ADMIN)
|
||||
})
|
||||
|
||||
Convey("Should default to member permission level when updating a user with invalid permission level", func() {
|
||||
userID := userIds[0]
|
||||
team := group1.Result
|
||||
addMemberCmd := m.AddTeamMemberCommand{OrgId: testOrgId, TeamId: team.Id, UserId: userID}
|
||||
addMemberCmd := models.AddTeamMemberCommand{OrgId: testOrgId, TeamId: team.Id, UserId: userID}
|
||||
err = AddTeamMember(&addMemberCmd)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
qBeforeUpdate := &m.GetTeamMembersQuery{OrgId: testOrgId, TeamId: team.Id}
|
||||
qBeforeUpdate := &models.GetTeamMembersQuery{OrgId: testOrgId, TeamId: team.Id}
|
||||
err = GetTeamMembers(qBeforeUpdate)
|
||||
So(err, ShouldBeNil)
|
||||
So(qBeforeUpdate.Result[0].Permission, ShouldEqual, 0)
|
||||
|
||||
invalidPermissionLevel := m.PERMISSION_EDIT
|
||||
err = UpdateTeamMember(&m.UpdateTeamMemberCommand{
|
||||
invalidPermissionLevel := models.PERMISSION_EDIT
|
||||
err = UpdateTeamMember(&models.UpdateTeamMemberCommand{
|
||||
UserId: userID,
|
||||
OrgId: testOrgId,
|
||||
TeamId: team.Id,
|
||||
@@ -150,31 +150,31 @@ func TestTeamCommandsAndQueries(t *testing.T) {
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
qAfterUpdate := &m.GetTeamMembersQuery{OrgId: testOrgId, TeamId: team.Id}
|
||||
qAfterUpdate := &models.GetTeamMembersQuery{OrgId: testOrgId, TeamId: team.Id}
|
||||
err = GetTeamMembers(qAfterUpdate)
|
||||
So(err, ShouldBeNil)
|
||||
So(qAfterUpdate.Result[0].Permission, ShouldEqual, 0)
|
||||
})
|
||||
|
||||
Convey("Shouldn't be able to update a user not in the team.", func() {
|
||||
err = UpdateTeamMember(&m.UpdateTeamMemberCommand{
|
||||
err = UpdateTeamMember(&models.UpdateTeamMemberCommand{
|
||||
UserId: 1,
|
||||
OrgId: testOrgId,
|
||||
TeamId: group1.Result.Id,
|
||||
Permission: m.PERMISSION_ADMIN,
|
||||
Permission: models.PERMISSION_ADMIN,
|
||||
})
|
||||
|
||||
So(err, ShouldEqual, m.ErrTeamMemberNotFound)
|
||||
So(err, ShouldEqual, models.ErrTeamMemberNotFound)
|
||||
})
|
||||
|
||||
Convey("Should be able to search for teams", func() {
|
||||
query := &m.SearchTeamsQuery{OrgId: testOrgId, Query: "group", Page: 1}
|
||||
query := &models.SearchTeamsQuery{OrgId: testOrgId, Query: "group", Page: 1}
|
||||
err = SearchTeams(query)
|
||||
So(err, ShouldBeNil)
|
||||
So(len(query.Result.Teams), ShouldEqual, 2)
|
||||
So(query.Result.TotalCount, ShouldEqual, 2)
|
||||
|
||||
query2 := &m.SearchTeamsQuery{OrgId: testOrgId, Query: ""}
|
||||
query2 := &models.SearchTeamsQuery{OrgId: testOrgId, Query: ""}
|
||||
err = SearchTeams(query2)
|
||||
So(err, ShouldBeNil)
|
||||
So(len(query2.Result.Teams), ShouldEqual, 2)
|
||||
@@ -182,10 +182,10 @@ func TestTeamCommandsAndQueries(t *testing.T) {
|
||||
|
||||
Convey("Should be able to return all teams a user is member of", func() {
|
||||
groupId := group2.Result.Id
|
||||
err := AddTeamMember(&m.AddTeamMemberCommand{OrgId: testOrgId, TeamId: groupId, UserId: userIds[0]})
|
||||
err := AddTeamMember(&models.AddTeamMemberCommand{OrgId: testOrgId, TeamId: groupId, UserId: userIds[0]})
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
query := &m.GetTeamsByUserQuery{OrgId: testOrgId, UserId: userIds[0]}
|
||||
query := &models.GetTeamsByUserQuery{OrgId: testOrgId, UserId: userIds[0]}
|
||||
err = GetTeamsByUser(query)
|
||||
So(err, ShouldBeNil)
|
||||
So(len(query.Result), ShouldEqual, 1)
|
||||
@@ -194,66 +194,84 @@ func TestTeamCommandsAndQueries(t *testing.T) {
|
||||
})
|
||||
|
||||
Convey("Should be able to remove users from a group", func() {
|
||||
err = AddTeamMember(&m.AddTeamMemberCommand{OrgId: testOrgId, TeamId: group1.Result.Id, UserId: userIds[0]})
|
||||
err = AddTeamMember(&models.AddTeamMemberCommand{OrgId: testOrgId, TeamId: group1.Result.Id, UserId: userIds[0]})
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
err = RemoveTeamMember(&m.RemoveTeamMemberCommand{OrgId: testOrgId, TeamId: group1.Result.Id, UserId: userIds[0]})
|
||||
err = RemoveTeamMember(&models.RemoveTeamMemberCommand{OrgId: testOrgId, TeamId: group1.Result.Id, UserId: userIds[0]})
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
q2 := &m.GetTeamMembersQuery{OrgId: testOrgId, TeamId: group1.Result.Id}
|
||||
q2 := &models.GetTeamMembersQuery{OrgId: testOrgId, TeamId: group1.Result.Id}
|
||||
err = GetTeamMembers(q2)
|
||||
So(err, ShouldBeNil)
|
||||
So(len(q2.Result), ShouldEqual, 0)
|
||||
})
|
||||
|
||||
Convey("When ProtectLastAdmin is set to true", func() {
|
||||
err = AddTeamMember(&m.AddTeamMemberCommand{OrgId: testOrgId, TeamId: group1.Result.Id, UserId: userIds[0], Permission: m.PERMISSION_ADMIN})
|
||||
err = AddTeamMember(&models.AddTeamMemberCommand{OrgId: testOrgId, TeamId: group1.Result.Id, UserId: userIds[0], Permission: models.PERMISSION_ADMIN})
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
Convey("A user should not be able to remove the last admin", func() {
|
||||
err = RemoveTeamMember(&m.RemoveTeamMemberCommand{OrgId: testOrgId, TeamId: group1.Result.Id, UserId: userIds[0], ProtectLastAdmin: true})
|
||||
So(err, ShouldEqual, m.ErrLastTeamAdmin)
|
||||
err = RemoveTeamMember(&models.RemoveTeamMemberCommand{OrgId: testOrgId, TeamId: group1.Result.Id, UserId: userIds[0], ProtectLastAdmin: true})
|
||||
So(err, ShouldEqual, models.ErrLastTeamAdmin)
|
||||
})
|
||||
|
||||
Convey("A user should be able to remove an admin if there are other admins", func() {
|
||||
AddTeamMember(&m.AddTeamMemberCommand{OrgId: testOrgId, TeamId: group1.Result.Id, UserId: userIds[1], Permission: m.PERMISSION_ADMIN})
|
||||
err = RemoveTeamMember(&m.RemoveTeamMemberCommand{OrgId: testOrgId, TeamId: group1.Result.Id, UserId: userIds[0], ProtectLastAdmin: true})
|
||||
AddTeamMember(&models.AddTeamMemberCommand{OrgId: testOrgId, TeamId: group1.Result.Id, UserId: userIds[1], Permission: models.PERMISSION_ADMIN})
|
||||
err = RemoveTeamMember(&models.RemoveTeamMemberCommand{OrgId: testOrgId, TeamId: group1.Result.Id, UserId: userIds[0], ProtectLastAdmin: true})
|
||||
So(err, ShouldEqual, nil)
|
||||
})
|
||||
|
||||
Convey("A user should not be able to remove the admin permission for the last admin", func() {
|
||||
err = UpdateTeamMember(&m.UpdateTeamMemberCommand{OrgId: testOrgId, TeamId: group1.Result.Id, UserId: userIds[0], Permission: 0, ProtectLastAdmin: true})
|
||||
So(err, ShouldEqual, m.ErrLastTeamAdmin)
|
||||
err = UpdateTeamMember(&models.UpdateTeamMemberCommand{OrgId: testOrgId, TeamId: group1.Result.Id, UserId: userIds[0], Permission: 0, ProtectLastAdmin: true})
|
||||
So(err, ShouldEqual, models.ErrLastTeamAdmin)
|
||||
})
|
||||
|
||||
Convey("A user should be able to remove the admin permission if there are other admins", func() {
|
||||
AddTeamMember(&m.AddTeamMemberCommand{OrgId: testOrgId, TeamId: group1.Result.Id, UserId: userIds[1], Permission: m.PERMISSION_ADMIN})
|
||||
err = UpdateTeamMember(&m.UpdateTeamMemberCommand{OrgId: testOrgId, TeamId: group1.Result.Id, UserId: userIds[0], Permission: 0, ProtectLastAdmin: true})
|
||||
AddTeamMember(&models.AddTeamMemberCommand{OrgId: testOrgId, TeamId: group1.Result.Id, UserId: userIds[1], Permission: models.PERMISSION_ADMIN})
|
||||
err = UpdateTeamMember(&models.UpdateTeamMemberCommand{OrgId: testOrgId, TeamId: group1.Result.Id, UserId: userIds[0], Permission: 0, ProtectLastAdmin: true})
|
||||
So(err, ShouldEqual, nil)
|
||||
})
|
||||
})
|
||||
|
||||
Convey("Should be able to remove a group with users and permissions", func() {
|
||||
groupId := group2.Result.Id
|
||||
err := AddTeamMember(&m.AddTeamMemberCommand{OrgId: testOrgId, TeamId: groupId, UserId: userIds[1]})
|
||||
err := AddTeamMember(&models.AddTeamMemberCommand{OrgId: testOrgId, TeamId: groupId, UserId: userIds[1]})
|
||||
So(err, ShouldBeNil)
|
||||
err = AddTeamMember(&m.AddTeamMemberCommand{OrgId: testOrgId, TeamId: groupId, UserId: userIds[2]})
|
||||
err = AddTeamMember(&models.AddTeamMemberCommand{OrgId: testOrgId, TeamId: groupId, UserId: userIds[2]})
|
||||
So(err, ShouldBeNil)
|
||||
err = testHelperUpdateDashboardAcl(1, m.DashboardAcl{DashboardId: 1, OrgId: testOrgId, Permission: m.PERMISSION_EDIT, TeamId: groupId})
|
||||
err = testHelperUpdateDashboardAcl(1, models.DashboardAcl{DashboardId: 1, OrgId: testOrgId, Permission: models.PERMISSION_EDIT, TeamId: groupId})
|
||||
So(err, ShouldBeNil)
|
||||
err = DeleteTeam(&m.DeleteTeamCommand{OrgId: testOrgId, Id: groupId})
|
||||
err = DeleteTeam(&models.DeleteTeamCommand{OrgId: testOrgId, Id: groupId})
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
query := &m.GetTeamByIdQuery{OrgId: testOrgId, Id: groupId}
|
||||
query := &models.GetTeamByIdQuery{OrgId: testOrgId, Id: groupId}
|
||||
err = GetTeamById(query)
|
||||
So(err, ShouldEqual, m.ErrTeamNotFound)
|
||||
So(err, ShouldEqual, models.ErrTeamNotFound)
|
||||
|
||||
permQuery := &m.GetDashboardAclInfoListQuery{DashboardId: 1, OrgId: testOrgId}
|
||||
permQuery := &models.GetDashboardAclInfoListQuery{DashboardId: 1, OrgId: testOrgId}
|
||||
err = GetDashboardAclInfoList(permQuery)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
So(len(permQuery.Result), ShouldEqual, 0)
|
||||
})
|
||||
|
||||
Convey("Should be able to return if user is admin of teams or not", func() {
|
||||
groupId := group2.Result.Id
|
||||
err := AddTeamMember(&models.AddTeamMemberCommand{OrgId: testOrgId, TeamId: groupId, UserId: userIds[0]})
|
||||
So(err, ShouldBeNil)
|
||||
err = AddTeamMember(&models.AddTeamMemberCommand{OrgId: testOrgId, TeamId: groupId, UserId: userIds[1], Permission: models.PERMISSION_ADMIN})
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
query := &models.IsAdminOfTeamsQuery{SignedInUser: &models.SignedInUser{OrgId: testOrgId, UserId: userIds[0]}}
|
||||
err = IsAdminOfTeams(query)
|
||||
So(err, ShouldBeNil)
|
||||
So(query.Result, ShouldBeFalse)
|
||||
|
||||
query = &models.IsAdminOfTeamsQuery{SignedInUser: &models.SignedInUser{OrgId: testOrgId, UserId: userIds[1]}}
|
||||
err = IsAdminOfTeams(query)
|
||||
So(err, ShouldBeNil)
|
||||
So(query.Result, ShouldBeTrue)
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
@@ -44,12 +44,12 @@ export class UserPicker extends Component<Props, State> {
|
||||
}
|
||||
|
||||
return backendSrv
|
||||
.get(`/api/org/users?query=${query}&limit=10`)
|
||||
.get(`/api/org/users/lookup?query=${query}&limit=10`)
|
||||
.then((result: any) => {
|
||||
return result.map((user: any) => ({
|
||||
id: user.userId,
|
||||
value: user.userId,
|
||||
label: user.login === user.email ? user.login : `${user.login} - ${user.email}`,
|
||||
label: user.login,
|
||||
imgUrl: user.avatarUrl,
|
||||
login: user.login,
|
||||
}));
|
||||
|
||||
@@ -71,7 +71,7 @@ export class AlertTabCtrl {
|
||||
this.alertNotifications = [];
|
||||
this.alertHistory = [];
|
||||
|
||||
return this.backendSrv.get('/api/alert-notifications').then((res: any) => {
|
||||
return this.backendSrv.get('/api/alert-notifications/lookup').then((res: any) => {
|
||||
this.notifications = res;
|
||||
|
||||
this.initModel();
|
||||
|
||||
@@ -79,7 +79,7 @@ export class GettingStarted extends PureComponent<PanelProps, State> {
|
||||
href: 'org/users?gettingstarted',
|
||||
check: () => {
|
||||
return getBackendSrv()
|
||||
.get('/api/org/users')
|
||||
.get('/api/org/users/lookup')
|
||||
.then((res: any) => {
|
||||
return res.length > 1;
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user