mirror of https://github.com/grafana/grafana
commit
964a21b091
@ -1,116 +0,0 @@ |
|||||||
+++ |
|
||||||
title = "Permissions" |
|
||||||
description = "Grafana user permissions" |
|
||||||
keywords = ["grafana", "configuration", "documentation", "admin", "users", "permissions"] |
|
||||||
type = "docs" |
|
||||||
aliases = ["/reference/admin"] |
|
||||||
[menu.docs] |
|
||||||
name = "Permissions" |
|
||||||
parent = "admin" |
|
||||||
weight = 3 |
|
||||||
+++ |
|
||||||
|
|
||||||
# Permissions |
|
||||||
|
|
||||||
Grafana users have permissions that are determined by their: |
|
||||||
|
|
||||||
- **Organization Role** (Admin, Editor, Viewer) |
|
||||||
- Via **Team** memberships where the **Team** has been assigned specific permissions. |
|
||||||
- Via permissions assigned directly to user (on folders or dashboards) |
|
||||||
- The Grafana Admin (i.e. Super Admin) user flag. |
|
||||||
|
|
||||||
## Organization Roles |
|
||||||
|
|
||||||
Users can be belong to one or more organizations. A user's organization membership is tied to a role that defines what the user is allowed to do |
|
||||||
in that organization. |
|
||||||
|
|
||||||
### Admin Role |
|
||||||
|
|
||||||
Can do everything scoped to the organization. For example: |
|
||||||
|
|
||||||
- Add & Edit data sources. |
|
||||||
- Add & Edit organization users & teams. |
|
||||||
- Configure App plugins & set org settings. |
|
||||||
|
|
||||||
### Editor Role |
|
||||||
|
|
||||||
- Can create and modify dashboards & alert rules. This can be disabled on specific folders and dashboards. |
|
||||||
- **Cannot** create or edit data sources nor invite new users. |
|
||||||
|
|
||||||
### Viewer Role |
|
||||||
|
|
||||||
- View any dashboard. This can be disabled on specific folders and dashboards. |
|
||||||
- **Cannot** create or edit dashboards nor data sources. |
|
||||||
|
|
||||||
This role can be tweaked via Grafana server setting [viewers_can_edit]({{< relref "installation/configuration.md#viewers-can-edit" >}}). If you set this to true users |
|
||||||
with **Viewer** can also make transient dashboard edits, meaning they can modify panels & queries but not save the changes (nor create new dashboards). |
|
||||||
Useful for public Grafana installations where you want anonymous users to be able to edit panels & queries but not save or create new dashboards. |
|
||||||
|
|
||||||
## Grafana Admin |
|
||||||
|
|
||||||
This admin flag makes a user a `Super Admin`. This means they can access the `Server Admin` views where all users and organizations can be administrated. |
|
||||||
|
|
||||||
### Dashboard & Folder Permissions |
|
||||||
|
|
||||||
{{< docs-imagebox img="/img/docs/v50/folder_permissions.png" max-width="500px" class="docs-image--right" >}} |
|
||||||
|
|
||||||
For dashboards and dashboard folders there is a **Permissions** page that make it possible to |
|
||||||
remove the default role based permissions for Editors and Viewers. It's here you can add and assign permissions to specific **Users** and **Teams**. |
|
||||||
|
|
||||||
You can assign & remove permissions for **Organization Roles**, **Users** and **Teams**. |
|
||||||
|
|
||||||
Permission levels: |
|
||||||
|
|
||||||
- **Admin**: Can edit & create dashboards and edit permissions. |
|
||||||
- **Edit**: Can edit & create dashboards. **Cannot** edit folder/dashboard permissions. |
|
||||||
- **View**: Can only view existing dashboards/folders. |
|
||||||
|
|
||||||
#### Restricting Access |
|
||||||
|
|
||||||
The highest permission always wins so if you for example want to hide a folder or dashboard from others you need to remove the **Organization Role** based permission from the Access Control List (ACL). |
|
||||||
|
|
||||||
- You cannot override permissions for users with the **Org Admin Role**. Admins always have access to everything. |
|
||||||
- A more specific permission with a lower permission level will not have any effect if a more general rule exists with higher permission level. You need to remove or lower the permission level of the more general rule. |
|
||||||
|
|
||||||
#### How Grafana Resolves Multiple Permissions - Examples |
|
||||||
|
|
||||||
##### Example 1 (`user1` has the Editor Role) |
|
||||||
|
|
||||||
Permissions for a dashboard: |
|
||||||
|
|
||||||
- `Everyone with Editor Role Can Edit` |
|
||||||
- `user1 Can View` |
|
||||||
|
|
||||||
Result: `user1` has Edit permission as the highest permission always wins. |
|
||||||
|
|
||||||
##### Example 2 (`user1` has the Viewer Role and is a member of `team1`) |
|
||||||
|
|
||||||
Permissions for a dashboard: |
|
||||||
|
|
||||||
- `Everyone with Viewer Role Can View` |
|
||||||
- `user1 Can Edit` |
|
||||||
- `team1 Can Admin` |
|
||||||
|
|
||||||
Result: `user1` has Admin permission as the highest permission always wins. |
|
||||||
|
|
||||||
##### Example 3 |
|
||||||
|
|
||||||
Permissions for a dashboard: |
|
||||||
|
|
||||||
- `user1 Can Admin (inherited from parent folder)` |
|
||||||
- `user1 Can Edit` |
|
||||||
|
|
||||||
Result: You cannot override to a lower permission. `user1` has Admin permission as the highest permission always wins. |
|
||||||
|
|
||||||
- **View**: Can only view existing dashboards/folders. |
|
||||||
- You cannot override permissions for users with **Org Admin Role** |
|
||||||
- A more specific permission with lower permission level will not have any effect if a more general rule exists with higher permission level. For example if "Everyone with Editor Role Can Edit" exists in the ACL list then **John Doe** will still have Edit permission even after you have specifically added a permission for this user with the permission set to **View**. You need to remove or lower the permission level of the more general rule. |
|
||||||
|
|
||||||
### Data source permissions |
|
||||||
|
|
||||||
Permissions on dashboards and folders **do not** include permissions on data sources. A user with `Viewer` role |
|
||||||
can still issue any possible query to a data source, not just those queries that exist on dashboards he/she has access to. |
|
||||||
We hope to add permissions on data sources in a future release. Until then **do not** view dashboard permissions as a secure |
|
||||||
way to restrict user data access. Dashboard permissions only limits what dashboards & folders a user can view & edit not which |
|
||||||
data sources a user can access nor what queries a user can issue. |
|
||||||
|
|
@ -0,0 +1,43 @@ |
|||||||
|
+++ |
||||||
|
title = "Enhanced LDAP Integration" |
||||||
|
description = "Grafana Enhanced LDAP Integration Guide " |
||||||
|
keywords = ["grafana", "configuration", "documentation", "ldap", "active directory", "enterprise"] |
||||||
|
type = "docs" |
||||||
|
[menu.docs] |
||||||
|
name = "Enhanced LDAP" |
||||||
|
identifier = "enhanced-ldap" |
||||||
|
parent = "authentication" |
||||||
|
weight = 3 |
||||||
|
+++ |
||||||
|
|
||||||
|
# Enhanced LDAP Integration |
||||||
|
|
||||||
|
> Enhanced LDAP Integration is only available in Grafana Enterprise. Read more about [Grafana Enterprise]({{< relref "enterprise/index.md" >}}). |
||||||
|
|
||||||
|
The enhanced LDAP integration adds additional functionality on top of the [existing LDAP integration]({{< relref "auth/ldap.md" >}}). |
||||||
|
|
||||||
|
## LDAP Group Synchronization for Teams |
||||||
|
|
||||||
|
{{< docs-imagebox img="/img/docs/enterprise/team_members_ldap.png" class="docs-image--no-shadow docs-image--right" max-width= "600px" >}} |
||||||
|
|
||||||
|
With the enhanced LDAP integration it's possible to setup synchronization between LDAP groups and teams. This enables LDAP users which are members |
||||||
|
of certain LDAP groups to automatically be added/removed as members to certain teams in Grafana. Currently the synchronization will only happen every |
||||||
|
time a user logs in, but an active background synchronization is currently being developed. |
||||||
|
|
||||||
|
Grafana keeps track of all synchronized users in teams and you can see which users have been synchronized from LDAP in the team members list, see `LDAP` label in screenshot. |
||||||
|
This mechanism allows Grafana to remove an existing synchronized user from a team when its LDAP group membership changes. This mechanism also enables you to manually add |
||||||
|
a user as member of a team and it will not be removed when the user signs in. This gives you flexibility to combine LDAP group memberships and Grafana team memberships. |
||||||
|
|
||||||
|
<div class="clearfix"></div> |
||||||
|
|
||||||
|
### Enable LDAP group synchronization for a team |
||||||
|
|
||||||
|
{{< docs-imagebox img="/img/docs/enterprise/team_add_external_group.png" class="docs-image--no-shadow docs-image--right" max-width= "600px" >}} |
||||||
|
|
||||||
|
1. Navigate to Configuration / Teams. |
||||||
|
2. Select a team. |
||||||
|
3. Select the External group sync tab and click on the `Add group` button. |
||||||
|
4. Insert LDAP distinguished name (DN) of LDAP group you want to synchronize with the team. |
||||||
|
5. Click on `Add group` button to save. |
||||||
|
|
||||||
|
<div class="clearfix"></div> |
@ -0,0 +1,67 @@ |
|||||||
|
+++ |
||||||
|
title = "Grafana Enterprise" |
||||||
|
description = "Grafana Enterprise overview" |
||||||
|
keywords = ["grafana", "documentation", "datasource", "permissions", "ldap", "licensing", "enterprise"] |
||||||
|
type = "docs" |
||||||
|
[menu.docs] |
||||||
|
name = "Grafana Enterprise" |
||||||
|
identifier = "enterprise" |
||||||
|
weight = 30 |
||||||
|
+++ |
||||||
|
|
||||||
|
# Grafana Enterprise |
||||||
|
|
||||||
|
Grafana Enterprise is a commercial edition of Grafana that includes additional features not found in the open source |
||||||
|
version. |
||||||
|
|
||||||
|
Building on everything you already know and love about Grafana, Grafana Enterprise adds premium data sources, |
||||||
|
advanced authentication options, more permission controls, 24x7x365 support, and training from the core Grafana team. |
||||||
|
|
||||||
|
Grafana Enterprise includes all of the features found in the open source edition and more. |
||||||
|
|
||||||
|
___ |
||||||
|
|
||||||
|
### Enhanced LDAP Integration |
||||||
|
|
||||||
|
With Grafana Enterprise you can set up synchronization between LDAP Groups and Teams. [Learn More]({{< relref "auth/enhanced_ldap.md" >}}). |
||||||
|
|
||||||
|
### Datasource Permissions |
||||||
|
|
||||||
|
Datasource permissions allow you to restrict query access to only specific Teams and Users. [Learn More]({{< relref "permissions/datasource_permissions.md" >}}). |
||||||
|
|
||||||
|
### Premium Plugins |
||||||
|
|
||||||
|
With a Grafana Enterprise licence you will get access to premium plugins, including: |
||||||
|
|
||||||
|
* [Splunk](https://grafana.com/plugins/grafana-splunk-datasource) |
||||||
|
* [AppDynamics](https://grafana.com/plugins/dlopes7-appdynamics-datasource) |
||||||
|
* [DataDog](https://grafana.com/plugins/grafana-datadog-datasource) |
||||||
|
* [Dynatrace](https://grafana.com/plugins/grafana-dynatrace-datasource) |
||||||
|
* [New Relic](https://grafana.com/plugins/grafana-newrelic-datasource) |
||||||
|
|
||||||
|
## Try Grafana Enterprise |
||||||
|
|
||||||
|
You can learn more about Grafana Enterprise [here](https://grafana.com/enterprise). To purchase or obtain a trial license contact |
||||||
|
the Grafana Labs [Sales Team](https://grafana.com/contact?about=support&topic=Grafana%20Enterprise). |
||||||
|
|
||||||
|
## License file management |
||||||
|
|
||||||
|
To download your Grafana Enterprise license log in to your [Grafana.com](https://grafana.com) account and go to your **Org |
||||||
|
Profile**. In the side menu there is a section for Grafana Enterprise licenses. At the bottom of the license |
||||||
|
details page there is **Download Token** link that will download the *license.jwt* file containing your license. |
||||||
|
|
||||||
|
Place the *license.jwt* file in Grafana's data folder. This is usually located at `/var/lib/grafana/data` on linux systems. |
||||||
|
|
||||||
|
You can also configure a custom location for the license file via the ini setting: |
||||||
|
|
||||||
|
```bash |
||||||
|
[enterprise] |
||||||
|
license_path = /company/secrets/license.jwt |
||||||
|
``` |
||||||
|
|
||||||
|
This setting can also be set via ENV variable which is useful if you're running Grafana via docker and have a custom |
||||||
|
volume where you have placed the license file. In this case set the ENV variable `GF_ENTERPRISE_LICENSE_PATH` to point |
||||||
|
to the location of your license file. |
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,249 @@ |
|||||||
|
+++ |
||||||
|
title = "Datasource Permissions HTTP API " |
||||||
|
description = "Grafana Datasource Permissions HTTP API" |
||||||
|
keywords = ["grafana", "http", "documentation", "api", "datasource", "permission", "permissions", "acl", "enterprise"] |
||||||
|
aliases = ["/http_api/datasourcepermissions/"] |
||||||
|
type = "docs" |
||||||
|
[menu.docs] |
||||||
|
name = "Datasource Permissions" |
||||||
|
parent = "http_api" |
||||||
|
+++ |
||||||
|
|
||||||
|
# Datasource Permissions API |
||||||
|
|
||||||
|
> Datasource Permissions is only available in Grafana Enterprise. Read more about [Grafana Enterprise]({{< relref "enterprise/index.md" >}}). |
||||||
|
|
||||||
|
This API can be used to enable, disable, list, add and remove permissions for a datasource. |
||||||
|
|
||||||
|
Permissions can be set for a user or a team. Permissions cannot be set for Admins - they always have access to everything. |
||||||
|
|
||||||
|
The permission levels for the permission field: |
||||||
|
|
||||||
|
- 1 = Query |
||||||
|
|
||||||
|
## Enable permissions for a datasource |
||||||
|
|
||||||
|
`POST /api/datasources/:id/enable-permissions` |
||||||
|
|
||||||
|
Enables permissions for the datasource with the given `id`. No one except Org Admins will be able to query the datasource until permissions have been added which permit certain users or teams to query the datasource. |
||||||
|
|
||||||
|
**Example request**: |
||||||
|
|
||||||
|
```http |
||||||
|
POST /api/datasources/1/enable-permissions |
||||||
|
Accept: application/json |
||||||
|
Content-Type: application/json |
||||||
|
Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk |
||||||
|
|
||||||
|
{} |
||||||
|
``` |
||||||
|
|
||||||
|
**Example response**: |
||||||
|
|
||||||
|
```http |
||||||
|
HTTP/1.1 200 OK |
||||||
|
Content-Type: application/json; charset=UTF-8 |
||||||
|
Content-Length: 35 |
||||||
|
|
||||||
|
{"message":"Datasource permissions enabled"} |
||||||
|
``` |
||||||
|
|
||||||
|
Status Codes: |
||||||
|
|
||||||
|
- **200** - Ok |
||||||
|
- **400** - Permissions cannot be enabled, see response body for details |
||||||
|
- **401** - Unauthorized |
||||||
|
- **403** - Access denied |
||||||
|
- **404** - Datasource not found |
||||||
|
|
||||||
|
## Disable permissions for a datasource |
||||||
|
|
||||||
|
`POST /api/datasources/:id/disable-permissions` |
||||||
|
|
||||||
|
Disables permissions for the datasource with the given `id`. All existing permissions will be removed and anyone will be able to query the datasource. |
||||||
|
|
||||||
|
**Example request**: |
||||||
|
|
||||||
|
```http |
||||||
|
POST /api/datasources/1/disable-permissions |
||||||
|
Accept: application/json |
||||||
|
Content-Type: application/json |
||||||
|
Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk |
||||||
|
|
||||||
|
{} |
||||||
|
``` |
||||||
|
|
||||||
|
**Example response**: |
||||||
|
|
||||||
|
```http |
||||||
|
HTTP/1.1 200 OK |
||||||
|
Content-Type: application/json; charset=UTF-8 |
||||||
|
Content-Length: 35 |
||||||
|
|
||||||
|
{"message":"Datasource permissions disabled"} |
||||||
|
``` |
||||||
|
|
||||||
|
Status Codes: |
||||||
|
|
||||||
|
- **200** - Ok |
||||||
|
- **400** - Permissions cannot be disabled, see response body for details |
||||||
|
- **401** - Unauthorized |
||||||
|
- **403** - Access denied |
||||||
|
- **404** - Datasource not found |
||||||
|
|
||||||
|
## Get permissions for a datasource |
||||||
|
|
||||||
|
`GET /api/datasources/:id/permissions` |
||||||
|
|
||||||
|
Gets all existing permissions for the datasource with the given `id`. |
||||||
|
|
||||||
|
**Example request**: |
||||||
|
|
||||||
|
```http |
||||||
|
GET /api/datasources/1/permissions HTTP/1.1 |
||||||
|
Accept: application/json |
||||||
|
Content-Type: application/json |
||||||
|
Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk |
||||||
|
``` |
||||||
|
|
||||||
|
**Example Response** |
||||||
|
|
||||||
|
```http |
||||||
|
HTTP/1.1 200 OK |
||||||
|
Content-Type: application/json; charset=UTF-8 |
||||||
|
Content-Length: 551 |
||||||
|
|
||||||
|
{ |
||||||
|
"datasourceId": 1, |
||||||
|
"enabled": true, |
||||||
|
"permissions": |
||||||
|
[ |
||||||
|
{ |
||||||
|
"id": 1, |
||||||
|
"datasourceId": 1, |
||||||
|
"userId": 1, |
||||||
|
"userLogin": "user", |
||||||
|
"userEmail": "user@test.com", |
||||||
|
"userAvatarUrl": "/avatar/46d229b033af06a191ff2267bca9ae56", |
||||||
|
"permission": 1, |
||||||
|
"permissionName": "Query", |
||||||
|
"created": "2017-06-20T02:00:00+02:00", |
||||||
|
"updated": "2017-06-20T02:00:00+02:00", |
||||||
|
}, |
||||||
|
{ |
||||||
|
"id": 2, |
||||||
|
"datasourceId": 1, |
||||||
|
"teamId": 1, |
||||||
|
"team": "A Team", |
||||||
|
"teamAvatarUrl": "/avatar/46d229b033af06a191ff2267bca9ae56", |
||||||
|
"permission": 1, |
||||||
|
"permissionName": "Query", |
||||||
|
"created": "2017-06-20T02:00:00+02:00", |
||||||
|
"updated": "2017-06-20T02:00:00+02:00", |
||||||
|
} |
||||||
|
] |
||||||
|
} |
||||||
|
``` |
||||||
|
|
||||||
|
Status Codes: |
||||||
|
|
||||||
|
- **200** - Ok |
||||||
|
- **401** - Unauthorized |
||||||
|
- **403** - Access denied |
||||||
|
- **404** - Datasource not found |
||||||
|
|
||||||
|
## Add permission for a datasource |
||||||
|
|
||||||
|
`POST /api/datasources/:id/permissions` |
||||||
|
|
||||||
|
Adds a user permission for the datasource with the given `id`. |
||||||
|
|
||||||
|
**Example request**: |
||||||
|
|
||||||
|
```http |
||||||
|
POST /api/datasources/1/permissions |
||||||
|
Accept: application/json |
||||||
|
Content-Type: application/json |
||||||
|
Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk |
||||||
|
|
||||||
|
{ |
||||||
|
"userId": 1, |
||||||
|
"permission": 1 |
||||||
|
} |
||||||
|
``` |
||||||
|
|
||||||
|
**Example response**: |
||||||
|
|
||||||
|
```http |
||||||
|
HTTP/1.1 200 OK |
||||||
|
Content-Type: application/json; charset=UTF-8 |
||||||
|
Content-Length: 35 |
||||||
|
|
||||||
|
{"message":"Datasource permission added"} |
||||||
|
``` |
||||||
|
|
||||||
|
Adds a team permission for the datasource with the given `id`. |
||||||
|
|
||||||
|
**Example request**: |
||||||
|
|
||||||
|
```http |
||||||
|
POST /api/datasources/1/permissions |
||||||
|
Accept: application/json |
||||||
|
Content-Type: application/json |
||||||
|
Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk |
||||||
|
|
||||||
|
{ |
||||||
|
"teamId": 1, |
||||||
|
"permission": 1 |
||||||
|
} |
||||||
|
``` |
||||||
|
|
||||||
|
**Example response**: |
||||||
|
|
||||||
|
```http |
||||||
|
HTTP/1.1 200 OK |
||||||
|
Content-Type: application/json; charset=UTF-8 |
||||||
|
Content-Length: 35 |
||||||
|
|
||||||
|
{"message":"Datasource permission added"} |
||||||
|
``` |
||||||
|
|
||||||
|
Status Codes: |
||||||
|
|
||||||
|
- **200** - Ok |
||||||
|
- **400** - Permission cannot be added, see response body for details |
||||||
|
- **401** - Unauthorized |
||||||
|
- **403** - Access denied |
||||||
|
- **404** - Datasource not found |
||||||
|
|
||||||
|
## Remove permission for a datasource |
||||||
|
|
||||||
|
`DELETE /api/datasources/:id/permissions/:permissionId` |
||||||
|
|
||||||
|
Removes the permission with the given `permissionId` for the datasource with the given `id`. |
||||||
|
|
||||||
|
**Example request**: |
||||||
|
|
||||||
|
```http |
||||||
|
DELETE /api/datasources/1/permissions/2 |
||||||
|
Accept: application/json |
||||||
|
Content-Type: application/json |
||||||
|
Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk |
||||||
|
``` |
||||||
|
|
||||||
|
**Example response**: |
||||||
|
|
||||||
|
```http |
||||||
|
HTTP/1.1 200 OK |
||||||
|
Content-Type: application/json; charset=UTF-8 |
||||||
|
Content-Length: 35 |
||||||
|
|
||||||
|
{"message":"Datasource permission removed"} |
||||||
|
``` |
||||||
|
|
||||||
|
Status Codes: |
||||||
|
|
||||||
|
- **200** - Ok |
||||||
|
- **401** - Unauthorized |
||||||
|
- **403** - Access denied |
||||||
|
- **404** - Datasource not found or permission not found |
@ -0,0 +1,111 @@ |
|||||||
|
+++ |
||||||
|
title = "External Group Sync HTTP API " |
||||||
|
description = "Grafana External Group Sync HTTP API" |
||||||
|
keywords = ["grafana", "http", "documentation", "api", "team", "teams", "group", "member", "enterprise"] |
||||||
|
aliases = ["/http_api/external_group_sync/"] |
||||||
|
type = "docs" |
||||||
|
[menu.docs] |
||||||
|
name = "External Group Sync" |
||||||
|
parent = "http_api" |
||||||
|
+++ |
||||||
|
|
||||||
|
# External Group Synchronization API |
||||||
|
|
||||||
|
> External Group Synchronization is only available in Grafana Enterprise. Read more about [Grafana Enterprise]({{< relref "enterprise/index.md" >}}). |
||||||
|
|
||||||
|
## Get External Groups |
||||||
|
|
||||||
|
`GET /api/teams/:teamId/groups` |
||||||
|
|
||||||
|
**Example Request**: |
||||||
|
|
||||||
|
```http |
||||||
|
GET /api/teams/1/groups HTTP/1.1 |
||||||
|
Accept: application/json |
||||||
|
Content-Type: application/json |
||||||
|
Authorization: Basic YWRtaW46YWRtaW4= |
||||||
|
``` |
||||||
|
|
||||||
|
**Example Response**: |
||||||
|
|
||||||
|
```http |
||||||
|
HTTP/1.1 200 |
||||||
|
Content-Type: application/json |
||||||
|
|
||||||
|
[ |
||||||
|
{ |
||||||
|
"orgId": 1, |
||||||
|
"teamId": 1, |
||||||
|
"groupId": "cn=editors,ou=groups,dc=grafana,dc=org" |
||||||
|
} |
||||||
|
] |
||||||
|
``` |
||||||
|
|
||||||
|
Status Codes: |
||||||
|
|
||||||
|
- **200** - Ok |
||||||
|
- **401** - Unauthorized |
||||||
|
- **403** - Permission denied |
||||||
|
|
||||||
|
## Add External Group |
||||||
|
|
||||||
|
`POST /api/teams/:teamId/groups` |
||||||
|
|
||||||
|
**Example Request**: |
||||||
|
|
||||||
|
```http |
||||||
|
POST /api/teams/1/members HTTP/1.1 |
||||||
|
Accept: application/json |
||||||
|
Content-Type: application/json |
||||||
|
Authorization: Basic YWRtaW46YWRtaW4= |
||||||
|
|
||||||
|
{ |
||||||
|
"groupId": "cn=editors,ou=groups,dc=grafana,dc=org" |
||||||
|
} |
||||||
|
``` |
||||||
|
|
||||||
|
**Example Response**: |
||||||
|
|
||||||
|
```http |
||||||
|
HTTP/1.1 200 |
||||||
|
Content-Type: application/json |
||||||
|
|
||||||
|
{"message":"Group added to Team"} |
||||||
|
``` |
||||||
|
|
||||||
|
Status Codes: |
||||||
|
|
||||||
|
- **200** - Ok |
||||||
|
- **400** - Group is already added to this team |
||||||
|
- **401** - Unauthorized |
||||||
|
- **403** - Permission denied |
||||||
|
- **404** - Team not found |
||||||
|
|
||||||
|
## Remove External Group |
||||||
|
|
||||||
|
`DELETE /api/teams/:teamId/groups/:groupId` |
||||||
|
|
||||||
|
**Example Request**: |
||||||
|
|
||||||
|
```http |
||||||
|
DELETE /api/teams/1/groups/cn=editors,ou=groups,dc=grafana,dc=org HTTP/1.1 |
||||||
|
Accept: application/json |
||||||
|
Content-Type: application/json |
||||||
|
Authorization: Basic YWRtaW46YWRtaW4= |
||||||
|
``` |
||||||
|
|
||||||
|
**Example Response**: |
||||||
|
|
||||||
|
```http |
||||||
|
HTTP/1.1 200 |
||||||
|
Content-Type: application/json |
||||||
|
|
||||||
|
{"message":"Team Group removed"} |
||||||
|
``` |
||||||
|
|
||||||
|
Status Codes: |
||||||
|
|
||||||
|
- **200** - Ok |
||||||
|
- **401** - Unauthorized |
||||||
|
- **403** - Permission denied |
||||||
|
- **404** - Team not found/Group not found |
@ -0,0 +1,73 @@ |
|||||||
|
+++ |
||||||
|
title = "Dashboard & Folder Permissions" |
||||||
|
description = "Grafana Dashboard & Folder Permissions Guide " |
||||||
|
keywords = ["grafana", "configuration", "documentation", "dashboard", "folder", "permissions", "teams"] |
||||||
|
type = "docs" |
||||||
|
[menu.docs] |
||||||
|
name = "Dashboard & Folder" |
||||||
|
identifier = "dashboard-folder-permissions" |
||||||
|
parent = "permissions" |
||||||
|
weight = 3 |
||||||
|
+++ |
||||||
|
|
||||||
|
# Dashboard & Folder Permissions |
||||||
|
|
||||||
|
{{< docs-imagebox img="/img/docs/v50/folder_permissions.png" max-width="500px" class="docs-image--right" >}} |
||||||
|
|
||||||
|
For dashboards and dashboard folders there is a **Permissions** page that make it possible to |
||||||
|
remove the default role based permissions for Editors and Viewers. On this page you can add and assign permissions to specific **Users** and **Teams**. |
||||||
|
|
||||||
|
You can assign & remove permissions for **Organization Roles**, **Users** and **Teams**. |
||||||
|
|
||||||
|
Permission levels: |
||||||
|
|
||||||
|
- **Admin**: Can edit & create dashboards and edit permissions. |
||||||
|
- **Edit**: Can edit & create dashboards. **Cannot** edit folder/dashboard permissions. |
||||||
|
- **View**: Can only view existing dashboards/folders. |
||||||
|
|
||||||
|
## Restricting Access |
||||||
|
|
||||||
|
The highest permission always wins so if you for example want to hide a folder or dashboard from others you need to remove the **Organization Role** based permission from the Access Control List (ACL). |
||||||
|
|
||||||
|
- You cannot override permissions for users with the **Org Admin Role**. Admins always have access to everything. |
||||||
|
- A more specific permission with a lower permission level will not have any effect if a more general rule exists with higher permission level. You need to remove or lower the permission level of the more general rule. |
||||||
|
|
||||||
|
### How Grafana Resolves Multiple Permissions - Examples |
||||||
|
|
||||||
|
#### Example 1 (`user1` has the Editor Role) |
||||||
|
|
||||||
|
Permissions for a dashboard: |
||||||
|
|
||||||
|
- `Everyone with Editor Role Can Edit` |
||||||
|
- `user1 Can View` |
||||||
|
|
||||||
|
Result: `user1` has Edit permission as the highest permission always wins. |
||||||
|
|
||||||
|
#### Example 2 (`user1` has the Viewer Role and is a member of `team1`) |
||||||
|
|
||||||
|
Permissions for a dashboard: |
||||||
|
|
||||||
|
- `Everyone with Viewer Role Can View` |
||||||
|
- `user1 Can Edit` |
||||||
|
- `team1 Can Admin` |
||||||
|
|
||||||
|
Result: `user1` has Admin permission as the highest permission always wins. |
||||||
|
|
||||||
|
#### Example 3 |
||||||
|
|
||||||
|
Permissions for a dashboard: |
||||||
|
|
||||||
|
- `user1 Can Admin (inherited from parent folder)` |
||||||
|
- `user1 Can Edit` |
||||||
|
|
||||||
|
Result: You cannot override to a lower permission. `user1` has Admin permission as the highest permission always wins. |
||||||
|
|
||||||
|
## Summary |
||||||
|
|
||||||
|
- **View**: Can only view existing dashboards/folders. |
||||||
|
- You cannot override permissions for users with **Org Admin Role** |
||||||
|
- A more specific permission with lower permission level will not have any effect if a more general rule exists with higher permission level. |
||||||
|
|
||||||
|
For example if "Everyone with Editor Role Can Edit" exists in the ACL list then **John Doe** will still have Edit permission even after you have specifically added a permission for this user with the permission set to **View**. You need to remove or lower the permission level of the more general rule. |
||||||
|
- You cannot override permissions for users with **Org Admin Role** |
||||||
|
- A more specific permission with lower permission level will not have any effect if a more general rule exists with higher permission level. For example if "Everyone with Editor Role Can Edit" exists in the ACL list then **John Doe** will still have Edit permission even after you have specifically added a permission for this user with the permission set to **View**. You need to remove or lower the permission level of the more general rule. |
@ -0,0 +1,71 @@ |
|||||||
|
+++ |
||||||
|
title = "Datasource Permissions" |
||||||
|
description = "Grafana Datasource Permissions Guide " |
||||||
|
keywords = ["grafana", "configuration", "documentation", "datasource", "permissions", "users", "teams", "enterprise"] |
||||||
|
type = "docs" |
||||||
|
[menu.docs] |
||||||
|
name = "Datasource" |
||||||
|
identifier = "datasource-permissions" |
||||||
|
parent = "permissions" |
||||||
|
weight = 4 |
||||||
|
+++ |
||||||
|
|
||||||
|
# Datasource Permissions |
||||||
|
|
||||||
|
> Datasource Permissions is only available in Grafana Enterprise. Read more about [Grafana Enterprise]({{< relref "enterprise/index.md" >}}). |
||||||
|
|
||||||
|
Datasource permissions allows you to restrict access for users to query a datasource. For each datasource there is |
||||||
|
a permission page that makes it possible to enable permissions and restrict query permissions to specific |
||||||
|
**Users** and **Teams**. |
||||||
|
|
||||||
|
## Restricting Access - Enable Permissions |
||||||
|
|
||||||
|
{{< docs-imagebox img="/img/docs/enterprise/datasource_permissions_enable_still.png" class="docs-image--no-shadow docs-image--right" max-width= "600px" animated-gif="/img/docs/enterprise/datasource_permissions_enable.gif" >}} |
||||||
|
|
||||||
|
By default, permissions are disabled for datasources and a datasource in an organization can be queried by any user in |
||||||
|
that organization. For example a user with `Viewer` role can still issue any possible query to a datasource, not just |
||||||
|
those queries that exist on dashboards he/she has access to. |
||||||
|
|
||||||
|
When permissions are enabled for a datasource in an organization you will restrict admin and query access for that |
||||||
|
datasource to [admin users](/permissions/organization_roles/#admin-role) in that organization. |
||||||
|
|
||||||
|
**To enable permissions for a datasource:** |
||||||
|
|
||||||
|
1. Navigate to Configuration / Data Sources. |
||||||
|
2. Select the datasource you want to enable permissions for. |
||||||
|
3. Select the Permissions tab and click on the `Enable` button. |
||||||
|
|
||||||
|
<div class="clearfix"></div> |
||||||
|
|
||||||
|
## Allow users and teams to query a datasource |
||||||
|
|
||||||
|
{{< docs-imagebox img="/img/docs/enterprise/datasource_permissions_add_still.png" class="docs-image--no-shadow docs-image--right" max-width= "600px" animated-gif="/img/docs/enterprise/datasource_permissions_add.gif" >}} |
||||||
|
|
||||||
|
After you have [enabled permissions](#restricting-access-enable-permissions) for a datasource you can assign query |
||||||
|
permissions to users and teams which will allow access to query the datasource. |
||||||
|
|
||||||
|
**Assign query permission to users and teams:** |
||||||
|
|
||||||
|
1. Navigate to Configuration / Data Sources. |
||||||
|
2. Select the datasource you want to assign query permissions for. |
||||||
|
3. Select the Permissions tab. |
||||||
|
4. click on the `Add Permission` button. |
||||||
|
5. Select Team/User and find the team/user you want to allow query access and click on the `Save` button. |
||||||
|
|
||||||
|
<div class="clearfix"></div> |
||||||
|
|
||||||
|
## Restore Default Access - Disable Permissions |
||||||
|
|
||||||
|
{{< docs-imagebox img="/img/docs/enterprise/datasource_permissions_disable_still.png" class="docs-image--no-shadow docs-image--right" max-width= "600px" animated-gif="/img/docs/enterprise/datasource_permissions_disable.gif" >}} |
||||||
|
|
||||||
|
If you have enabled permissions for a datasource and want to return datasource permissions to the default, i.e. |
||||||
|
datasource can be queried by any user in that organization, you can disable permissions with a click of a button. |
||||||
|
Note that all existing permissions created for datasource will be deleted. |
||||||
|
|
||||||
|
**To disable permissions for a datasource:** |
||||||
|
|
||||||
|
1. Navigate to Configuration / Data Sources. |
||||||
|
2. Select the datasource you want to disable permissions for. |
||||||
|
3. Select the Permissions tab and click on the `Disable Permissions` button. |
||||||
|
|
||||||
|
<div class="clearfix"></div> |
@ -0,0 +1,12 @@ |
|||||||
|
+++ |
||||||
|
title = "Permissions" |
||||||
|
description = "Permissions" |
||||||
|
type = "docs" |
||||||
|
[menu.docs] |
||||||
|
name = "Permissions" |
||||||
|
identifier = "permissions" |
||||||
|
parent = "admin" |
||||||
|
weight = 3 |
||||||
|
+++ |
||||||
|
|
||||||
|
|
@ -0,0 +1,38 @@ |
|||||||
|
+++ |
||||||
|
title = "Organization Roles" |
||||||
|
description = "Grafana Organization Roles Guide " |
||||||
|
keywords = ["grafana", "configuration", "documentation", "organization", "roles", "permissions"] |
||||||
|
type = "docs" |
||||||
|
[menu.docs] |
||||||
|
name = "Organization Roles" |
||||||
|
identifier = "organization-roles" |
||||||
|
parent = "permissions" |
||||||
|
weight = 2 |
||||||
|
+++ |
||||||
|
|
||||||
|
# Organization Roles |
||||||
|
|
||||||
|
Users can be belong to one or more organizations. A user's organization membership is tied to a role that defines what the user is allowed to do |
||||||
|
in that organization. |
||||||
|
|
||||||
|
## Admin Role |
||||||
|
|
||||||
|
Can do everything scoped to the organization. For example: |
||||||
|
|
||||||
|
- Add & Edit data sources. |
||||||
|
- Add & Edit organization users & teams. |
||||||
|
- Configure App plugins & set org settings. |
||||||
|
|
||||||
|
## Editor Role |
||||||
|
|
||||||
|
- Can create and modify dashboards & alert rules. This can be disabled on specific folders and dashboards. |
||||||
|
- **Cannot** create or edit data sources nor invite new users. |
||||||
|
|
||||||
|
## Viewer Role |
||||||
|
|
||||||
|
- View any dashboard. This can be disabled on specific folders and dashboards. |
||||||
|
- **Cannot** create or edit dashboards nor data sources. |
||||||
|
|
||||||
|
This role can be tweaked via Grafana server setting [viewers_can_edit]({{< relref "installation/configuration.md#viewers-can-edit" >}}). If you set this to true users |
||||||
|
with **Viewer** can also make transient dashboard edits, meaning they can modify panels & queries but not save the changes (nor create new dashboards). |
||||||
|
Useful for public Grafana installations where you want anonymous users to be able to edit panels & queries but not save or create new dashboards. |
@ -0,0 +1,42 @@ |
|||||||
|
+++ |
||||||
|
title = "Overview" |
||||||
|
description = "Overview for permissions" |
||||||
|
keywords = ["grafana", "configuration", "documentation", "admin", "users", "datasources", "permissions"] |
||||||
|
type = "docs" |
||||||
|
aliases = ["/reference/admin", "/administration/permissions/"] |
||||||
|
[menu.docs] |
||||||
|
name = "Overview" |
||||||
|
identifier = "overview-permissions" |
||||||
|
parent = "permissions" |
||||||
|
weight = 1 |
||||||
|
+++ |
||||||
|
|
||||||
|
# Permissions Overview |
||||||
|
|
||||||
|
Grafana users have permissions that are determined by their: |
||||||
|
|
||||||
|
- **Organization Role** (Admin, Editor, Viewer) |
||||||
|
- Via **Team** memberships where the **Team** has been assigned specific permissions. |
||||||
|
- Via permissions assigned directly to user (on folders, dashboards, datasources) |
||||||
|
- The Grafana Admin (i.e. Super Admin) user flag. |
||||||
|
|
||||||
|
## Grafana Admin |
||||||
|
|
||||||
|
This admin flag makes a user a `Super Admin`. This means they can access the `Server Admin` views where all users and organizations can be administrated. |
||||||
|
|
||||||
|
## Organization Roles |
||||||
|
|
||||||
|
Users can be belong to one or more organizations. A user's organization membership is tied to a role that defines what the user is allowed to do |
||||||
|
in that organization. Learn more about [Organization Roles]({{< relref "permissions/organization_roles.md" >}}). |
||||||
|
|
||||||
|
|
||||||
|
## Dashboard & Folder Permissions |
||||||
|
|
||||||
|
Dashboard and folder permissions allows you to remove the default role based permissions for Editors and Viewers and assign permissions to specific **Users** and **Teams**. Learn more about [Dashboard & Folder Permissions]({{< relref "permissions/dashboard_folder_permissions.md" >}}). |
||||||
|
|
||||||
|
## Datasource Permissions |
||||||
|
|
||||||
|
Per default, a datasource in an organization can be queried by any user in that organization. For example a user with `Viewer` role can still |
||||||
|
issue any possible query to a data source, not just those queries that exist on dashboards he/she has access to. |
||||||
|
|
||||||
|
Datasource permissions allows you to change the default permissions for datasources and restrict query permissions to specific **Users** and **Teams**. Read more about [Datasource Permissions]({{< relref "permissions/datasource_permissions.md" >}}). |
@ -1,83 +0,0 @@ |
|||||||
import React from 'react'; |
|
||||||
import classNames from 'classnames'; |
|
||||||
import { PanelModel } from '../panel_model'; |
|
||||||
import { DashboardModel } from '../dashboard_model'; |
|
||||||
import { store } from 'app/store/configureStore'; |
|
||||||
import { updateLocation } from 'app/core/actions'; |
|
||||||
|
|
||||||
interface PanelHeaderProps { |
|
||||||
panel: PanelModel; |
|
||||||
dashboard: DashboardModel; |
|
||||||
} |
|
||||||
|
|
||||||
export class PanelHeader extends React.Component<PanelHeaderProps, any> { |
|
||||||
onEditPanel = () => { |
|
||||||
store.dispatch( |
|
||||||
updateLocation({ |
|
||||||
query: { |
|
||||||
panelId: this.props.panel.id, |
|
||||||
edit: true, |
|
||||||
fullscreen: true, |
|
||||||
}, |
|
||||||
}) |
|
||||||
); |
|
||||||
}; |
|
||||||
|
|
||||||
onViewPanel = () => { |
|
||||||
store.dispatch( |
|
||||||
updateLocation({ |
|
||||||
query: { |
|
||||||
panelId: this.props.panel.id, |
|
||||||
edit: false, |
|
||||||
fullscreen: true, |
|
||||||
}, |
|
||||||
}) |
|
||||||
); |
|
||||||
}; |
|
||||||
|
|
||||||
render() { |
|
||||||
const isFullscreen = false; |
|
||||||
const isLoading = false; |
|
||||||
const panelHeaderClass = classNames({ 'panel-header': true, 'grid-drag-handle': !isFullscreen }); |
|
||||||
|
|
||||||
return ( |
|
||||||
<div className={panelHeaderClass}> |
|
||||||
<span className="panel-info-corner"> |
|
||||||
<i className="fa" /> |
|
||||||
<span className="panel-info-corner-inner" /> |
|
||||||
</span> |
|
||||||
|
|
||||||
{isLoading && ( |
|
||||||
<span className="panel-loading"> |
|
||||||
<i className="fa fa-spinner fa-spin" /> |
|
||||||
</span> |
|
||||||
)} |
|
||||||
|
|
||||||
<div className="panel-title-container"> |
|
||||||
<span className="panel-title"> |
|
||||||
<span className="icon-gf panel-alert-icon" /> |
|
||||||
<span className="panel-title-text">{this.props.panel.title}</span> |
|
||||||
<span className="panel-menu-container dropdown"> |
|
||||||
<span className="fa fa-caret-down panel-menu-toggle" data-toggle="dropdown" /> |
|
||||||
<ul className="dropdown-menu dropdown-menu--menu panel-menu" role="menu"> |
|
||||||
<li> |
|
||||||
<a onClick={this.onEditPanel}> |
|
||||||
<i className="fa fa-fw fa-edit" /> Edit |
|
||||||
</a> |
|
||||||
</li> |
|
||||||
<li> |
|
||||||
<a onClick={this.onViewPanel}> |
|
||||||
<i className="fa fa-fw fa-eye" /> View |
|
||||||
</a> |
|
||||||
</li> |
|
||||||
</ul> |
|
||||||
</span> |
|
||||||
<span className="panel-time-info"> |
|
||||||
<i className="fa fa-clock-o" /> 4m |
|
||||||
</span> |
|
||||||
</span> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
); |
|
||||||
} |
|
||||||
} |
|
@ -0,0 +1,51 @@ |
|||||||
|
import React, { PureComponent } from 'react'; |
||||||
|
import classNames from 'classnames'; |
||||||
|
|
||||||
|
import { PanelHeaderMenu } from './PanelHeaderMenu'; |
||||||
|
|
||||||
|
import { DashboardModel } from 'app/features/dashboard/dashboard_model'; |
||||||
|
import { PanelModel } from 'app/features/dashboard/panel_model'; |
||||||
|
|
||||||
|
export interface Props { |
||||||
|
panel: PanelModel; |
||||||
|
dashboard: DashboardModel; |
||||||
|
} |
||||||
|
|
||||||
|
export class PanelHeader extends PureComponent<Props> { |
||||||
|
render() { |
||||||
|
const isFullscreen = false; |
||||||
|
const isLoading = false; |
||||||
|
const panelHeaderClass = classNames({ 'panel-header': true, 'grid-drag-handle': !isFullscreen }); |
||||||
|
const { panel, dashboard } = this.props; |
||||||
|
|
||||||
|
return ( |
||||||
|
<div className={panelHeaderClass}> |
||||||
|
<span className="panel-info-corner"> |
||||||
|
<i className="fa" /> |
||||||
|
<span className="panel-info-corner-inner" /> |
||||||
|
</span> |
||||||
|
|
||||||
|
{isLoading && ( |
||||||
|
<span className="panel-loading"> |
||||||
|
<i className="fa fa-spinner fa-spin" /> |
||||||
|
</span> |
||||||
|
)} |
||||||
|
|
||||||
|
<div className="panel-title-container"> |
||||||
|
<div className="panel-title"> |
||||||
|
<span className="icon-gf panel-alert-icon" /> |
||||||
|
<span className="panel-title-text" data-toggle="dropdown"> |
||||||
|
{panel.title} <span className="fa fa-caret-down panel-menu-toggle" /> |
||||||
|
</span> |
||||||
|
|
||||||
|
<PanelHeaderMenu panel={panel} dashboard={dashboard} /> |
||||||
|
|
||||||
|
<span className="panel-time-info"> |
||||||
|
<i className="fa fa-clock-o" /> 4m |
||||||
|
</span> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,40 @@ |
|||||||
|
import React, { PureComponent } from 'react'; |
||||||
|
import { DashboardModel } from 'app/features/dashboard/dashboard_model'; |
||||||
|
import { PanelModel } from 'app/features/dashboard/panel_model'; |
||||||
|
import { PanelHeaderMenuItem } from './PanelHeaderMenuItem'; |
||||||
|
import { getPanelMenu } from 'app/features/dashboard/utils/getPanelMenu'; |
||||||
|
import { PanelMenuItem } from 'app/types/panel'; |
||||||
|
|
||||||
|
export interface Props { |
||||||
|
panel: PanelModel; |
||||||
|
dashboard: DashboardModel; |
||||||
|
} |
||||||
|
|
||||||
|
export class PanelHeaderMenu extends PureComponent<Props> { |
||||||
|
renderItems = (menu: PanelMenuItem[], isSubMenu = false) => { |
||||||
|
return ( |
||||||
|
<ul className="dropdown-menu dropdown-menu--menu panel-menu" role={isSubMenu ? '' : 'menu'}> |
||||||
|
{menu.map((menuItem, idx: number) => { |
||||||
|
return ( |
||||||
|
<PanelHeaderMenuItem |
||||||
|
key={`${menuItem.text}${idx}`} |
||||||
|
type={menuItem.type} |
||||||
|
text={menuItem.text} |
||||||
|
iconClassName={menuItem.iconClassName} |
||||||
|
onClick={menuItem.onClick} |
||||||
|
shortcut={menuItem.shortcut} |
||||||
|
> |
||||||
|
{menuItem.subMenu && this.renderItems(menuItem.subMenu, true)} |
||||||
|
</PanelHeaderMenuItem> |
||||||
|
); |
||||||
|
})} |
||||||
|
</ul> |
||||||
|
); |
||||||
|
}; |
||||||
|
|
||||||
|
render() { |
||||||
|
const { dashboard, panel } = this.props; |
||||||
|
const menu = getPanelMenu(dashboard, panel); |
||||||
|
return <div className="panel-menu-container dropdown">{this.renderItems(menu)}</div>; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,23 @@ |
|||||||
|
import React, { SFC } from 'react'; |
||||||
|
import { PanelMenuItem } from 'app/types/panel'; |
||||||
|
|
||||||
|
interface Props { |
||||||
|
children: any; |
||||||
|
} |
||||||
|
|
||||||
|
export const PanelHeaderMenuItem: SFC<Props & PanelMenuItem> = props => { |
||||||
|
const isSubMenu = props.type === 'submenu'; |
||||||
|
const isDivider = props.type === 'divider'; |
||||||
|
return isDivider ? ( |
||||||
|
<li className="divider" /> |
||||||
|
) : ( |
||||||
|
<li className={isSubMenu ? 'dropdown-submenu' : null}> |
||||||
|
<a onClick={props.onClick}> |
||||||
|
{props.iconClassName && <i className={props.iconClassName} />} |
||||||
|
<span className="dropdown-item-text">{props.text}</span> |
||||||
|
{props.shortcut && <span className="dropdown-menu-item-shortcut">{props.shortcut}</span>} |
||||||
|
</a> |
||||||
|
{props.children} |
||||||
|
</li> |
||||||
|
); |
||||||
|
}; |
@ -0,0 +1,120 @@ |
|||||||
|
import { updateLocation } from 'app/core/actions'; |
||||||
|
import { store } from 'app/store/configureStore'; |
||||||
|
|
||||||
|
import { removePanel, duplicatePanel, copyPanel, editPanelJson, sharePanel } from 'app/features/dashboard/utils/panel'; |
||||||
|
import { PanelModel } from 'app/features/dashboard/panel_model'; |
||||||
|
import { DashboardModel } from 'app/features/dashboard/dashboard_model'; |
||||||
|
import { PanelMenuItem } from 'app/types/panel'; |
||||||
|
|
||||||
|
export const getPanelMenu = (dashboard: DashboardModel, panel: PanelModel) => { |
||||||
|
const onViewPanel = () => { |
||||||
|
store.dispatch( |
||||||
|
updateLocation({ |
||||||
|
query: { |
||||||
|
panelId: panel.id, |
||||||
|
edit: false, |
||||||
|
fullscreen: true, |
||||||
|
}, |
||||||
|
partial: true, |
||||||
|
}) |
||||||
|
); |
||||||
|
}; |
||||||
|
|
||||||
|
const onEditPanel = () => { |
||||||
|
store.dispatch( |
||||||
|
updateLocation({ |
||||||
|
query: { |
||||||
|
panelId: panel.id, |
||||||
|
edit: true, |
||||||
|
fullscreen: true, |
||||||
|
}, |
||||||
|
partial: true, |
||||||
|
}) |
||||||
|
); |
||||||
|
}; |
||||||
|
|
||||||
|
const onSharePanel = () => { |
||||||
|
sharePanel(dashboard, panel); |
||||||
|
}; |
||||||
|
|
||||||
|
const onDuplicatePanel = () => { |
||||||
|
duplicatePanel(dashboard, panel); |
||||||
|
}; |
||||||
|
|
||||||
|
const onCopyPanel = () => { |
||||||
|
copyPanel(panel); |
||||||
|
}; |
||||||
|
|
||||||
|
const onEditPanelJson = () => { |
||||||
|
editPanelJson(dashboard, panel); |
||||||
|
}; |
||||||
|
|
||||||
|
const onRemovePanel = () => { |
||||||
|
removePanel(dashboard, panel, true); |
||||||
|
}; |
||||||
|
|
||||||
|
const menu: PanelMenuItem[] = []; |
||||||
|
|
||||||
|
menu.push({ |
||||||
|
text: 'View', |
||||||
|
iconClassName: 'fa fa-fw fa-eye', |
||||||
|
onClick: onViewPanel, |
||||||
|
shortcut: 'v', |
||||||
|
}); |
||||||
|
|
||||||
|
if (dashboard.meta.canEdit) { |
||||||
|
menu.push({ |
||||||
|
text: 'Edit', |
||||||
|
iconClassName: 'fa fa-fw fa-edit', |
||||||
|
onClick: onEditPanel, |
||||||
|
shortcut: 'e', |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
menu.push({ |
||||||
|
text: 'Share', |
||||||
|
iconClassName: 'fa fa-fw fa-share', |
||||||
|
onClick: onSharePanel, |
||||||
|
shortcut: 'p s', |
||||||
|
}); |
||||||
|
|
||||||
|
const subMenu: PanelMenuItem[] = []; |
||||||
|
|
||||||
|
if (!panel.fullscreen && dashboard.meta.canEdit) { |
||||||
|
subMenu.push({ |
||||||
|
text: 'Duplicate', |
||||||
|
onClick: onDuplicatePanel, |
||||||
|
shortcut: 'p d', |
||||||
|
}); |
||||||
|
|
||||||
|
subMenu.push({ |
||||||
|
text: 'Copy', |
||||||
|
onClick: onCopyPanel, |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
subMenu.push({ |
||||||
|
text: 'Panel JSON', |
||||||
|
onClick: onEditPanelJson, |
||||||
|
}); |
||||||
|
|
||||||
|
menu.push({ |
||||||
|
type: 'submenu', |
||||||
|
text: 'More...', |
||||||
|
iconClassName: 'fa fa-fw fa-cube', |
||||||
|
subMenu: subMenu, |
||||||
|
}); |
||||||
|
|
||||||
|
if (dashboard.meta.canEdit) { |
||||||
|
menu.push({ type: 'divider' }); |
||||||
|
|
||||||
|
menu.push({ |
||||||
|
text: 'Remove', |
||||||
|
iconClassName: 'fa fa-fw fa-trash', |
||||||
|
onClick: onRemovePanel, |
||||||
|
shortcut: 'p r', |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
return menu; |
||||||
|
}; |
@ -1,43 +0,0 @@ |
|||||||
FROM centos:6.6 |
|
||||||
|
|
||||||
RUN yum install -y yum-plugin-ovl initscripts curl tar gcc libc6-dev git gcc-c++ openssl-devel && \ |
|
||||||
yum install -y g++ make automake autoconf curl-devel zlib-devel httpd-devel apr-devel apr-util-devel sqlite-devel && \ |
|
||||||
yum install -y wget yum-utils bzip2 bzip2-devel && \ |
|
||||||
yum install -y fontconfig freetype freetype-devel fontconfig-devel libstdc++ && \ |
|
||||||
yum install -y rpm-build patch readline readline-devel libtool bison lzma && \ |
|
||||||
yum install -y which tar |
|
||||||
|
|
||||||
# Install RUBY 1.9.3 |
|
||||||
# install necessary utilities |
|
||||||
# RUN yum install -y which tar |
|
||||||
RUN gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 && \ |
|
||||||
curl -sSl https://raw.githubusercontent.com/rvm/rvm/master/binscripts/rvm-installer | bash -s stable && \ |
|
||||||
source /etc/profile.d/rvm.sh && \ |
|
||||||
/bin/bash -l -c "rvm requirements" && \ |
|
||||||
/bin/bash -l -c "rvm install 2.1.9" && \ |
|
||||||
/bin/bash -l -c "rvm use 2.1.9 --default" |
|
||||||
|
|
||||||
# install nodejs |
|
||||||
RUN curl --silent --location https://rpm.nodesource.com/setup_6.x | bash - && \ |
|
||||||
yum install -y nodejs --nogpgcheck |
|
||||||
|
|
||||||
ENV GOLANG_VERSION 1.11 |
|
||||||
|
|
||||||
RUN wget https://dl.yarnpkg.com/rpm/yarn.repo -O /etc/yum.repos.d/yarn.repo && \ |
|
||||||
yum install -y yarn --nogpgcheck && \ |
|
||||||
wget https://storage.googleapis.com/golang/go${GOLANG_VERSION}.linux-amd64.tar.gz && \ |
|
||||||
tar -C /usr/local -xzf go${GOLANG_VERSION}.linux-amd64.tar.gz |
|
||||||
|
|
||||||
|
|
||||||
ENV PATH /usr/local/go/bin:$PATH |
|
||||||
|
|
||||||
RUN mkdir -p /go/src /go/bin && chmod -R 777 /go |
|
||||||
|
|
||||||
ENV GOPATH /go |
|
||||||
ENV PATH /go/bin:$PATH |
|
||||||
|
|
||||||
ADD ./build.sh /tmp/ |
|
||||||
|
|
||||||
WORKDIR /tmp/ |
|
||||||
|
|
||||||
CMD ["./build.sh"] |
|
@ -1,17 +0,0 @@ |
|||||||
#!/bin/bash |
|
||||||
|
|
||||||
docker info && docker version |
|
||||||
mkdir -p ~/docker |
|
||||||
|
|
||||||
echo "Circle branch: ${CIRCLE_BRANCH}" |
|
||||||
echo "Circle tag: ${CIRCLE_TAG}" |
|
||||||
|
|
||||||
# try to load docker container from cache |
|
||||||
if [[ -e ~/docker/centos.tar ]]; then |
|
||||||
docker load -i ~/docker/centos.tar; |
|
||||||
else |
|
||||||
docker build --rm=false --tag "grafana/buildcontainer" ./scripts/build/ |
|
||||||
|
|
||||||
# save docker container so we don't have to recreate it next run |
|
||||||
docker save grafana/buildcontainer > ~/docker/centos.tar; |
|
||||||
fi |
|
Loading…
Reference in new issue