Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
N
nexpie-grafana-theme
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Registry
Registry
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Kornkitt Poolsup
nexpie-grafana-theme
Commits
a9a06ad5
Commit
a9a06ad5
authored
Sep 19, 2014
by
Torkel Ödegaard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Working on collaborators
parent
17057344
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
174 additions
and
98 deletions
+174
-98
grafana
+1
-1
pkg/api/api.go
+4
-12
pkg/api/api_account.go
+17
-11
pkg/api/api_auth.go
+48
-0
pkg/api/api_dashboard.go
+13
-17
pkg/api/api_login.go
+3
-20
pkg/api/api_routing.go
+36
-0
pkg/models/account.go
+43
-0
pkg/models/dashboards.go
+0
-34
pkg/stores/rethinkdb_accounts.go
+1
-0
views/index.html
+8
-3
No files found.
grafana
@
c65b7d15
Subproject commit
e5fd35db343109feec09d339d5d770dd1de1808a
Subproject commit
c65b7d159189f81b0d87ecc5b64be3ffbe332393
pkg/api/api.go
View file @
a9a06ad5
...
...
@@ -7,6 +7,7 @@ import (
"github.com/gin-gonic/gin"
"github.com/gorilla/sessions"
"github.com/torkelo/grafana-pro/pkg/components"
"github.com/torkelo/grafana-pro/pkg/models"
"github.com/torkelo/grafana-pro/pkg/stores"
)
...
...
@@ -61,9 +62,9 @@ func (self *HttpServer) ListenAndServe() {
func
(
self
*
HttpServer
)
index
(
c
*
gin
.
Context
)
{
viewModel
:=
&
IndexDto
{}
login
,
_
:=
c
.
Get
(
"login
"
)
if
login
!=
nil
{
viewModel
.
User
.
Login
=
login
.
(
string
)
userAccount
,
_
:=
c
.
Get
(
"userAccount
"
)
if
userAccount
!=
nil
{
viewModel
.
User
.
Login
=
userAccount
.
(
*
models
.
UserAccount
)
.
Login
}
c
.
HTML
(
200
,
"index.html"
,
viewModel
)
...
...
@@ -74,12 +75,3 @@ func CacheHeadersMiddleware() gin.HandlerFunc {
c
.
Writer
.
Header
()
.
Add
(
"Cache-Control"
,
"max-age=0, public, must-revalidate, proxy-revalidate"
)
}
}
// Api Handler Registration
var
routeHandlers
=
make
([]
routeHandlerRegisterFn
,
0
)
type
routeHandlerRegisterFn
func
(
self
*
HttpServer
)
func
addRoutes
(
fn
routeHandlerRegisterFn
)
{
routeHandlers
=
append
(
routeHandlers
,
fn
)
}
pkg/api/api_account.go
View file @
a9a06ad5
...
...
@@ -4,7 +4,7 @@ import "github.com/gin-gonic/gin"
func
init
()
{
addRoutes
(
func
(
self
*
HttpServer
)
{
self
.
router
.
POST
(
"/api/account/collaborators/add"
,
self
.
auth
()
,
self
.
addCollaborator
)
self
.
addRoute
(
"POST"
,
"/api/account/collaborators/add"
,
self
.
addCollaborator
)
})
}
...
...
@@ -12,28 +12,34 @@ type addCollaboratorDto struct {
Email
string
`json:"email" binding:"required"`
}
func
(
self
*
HttpServer
)
addCollaborator
(
c
*
gin
.
Context
)
{
func
(
self
*
HttpServer
)
addCollaborator
(
c
*
gin
.
Context
,
auth
*
authContext
)
{
var
model
addCollaboratorDto
if
!
c
.
EnsureBody
(
&
model
)
{
c
.
JSON
(
400
,
gin
.
H
{
"status"
:
"
bad request
"
})
c
.
JSON
(
400
,
gin
.
H
{
"status"
:
"
Collaborator not found
"
})
return
}
accountId
,
_
:=
c
.
Get
(
"accountId"
)
account
,
err
:=
self
.
store
.
GetAccount
(
accountId
.
(
int
))
if
err
!=
nil
{
c
.
JSON
(
401
,
gin
.
H
{
"status"
:
"Authentication error"
})
}
collaborator
,
err
:=
self
.
store
.
GetUserAccountLogin
(
model
.
Email
)
if
err
!=
nil
{
c
.
JSON
(
404
,
gin
.
H
{
"status"
:
"Collaborator not found"
})
return
}
account
.
AddCollaborator
(
collaborator
.
Id
)
userAccount
:=
auth
.
userAccount
if
collaborator
.
Id
==
userAccount
.
Id
{
c
.
JSON
(
400
,
gin
.
H
{
"status"
:
"Cannot add yourself as collaborator"
})
return
}
err
=
userAccount
.
AddCollaborator
(
collaborator
.
Id
)
if
err
!=
nil
{
c
.
JSON
(
400
,
gin
.
H
{
"status"
:
err
.
Error
()})
return
}
self
.
store
.
SaveUserAccount
(
a
ccount
)
self
.
store
.
SaveUserAccount
(
userA
ccount
)
c
.
JSON
(
200
,
gin
.
H
{
"status"
:
"Collaborator added"
})
}
pkg/api/api_auth.go
0 → 100644
View file @
a9a06ad5
package
api
import
(
"github.com/gin-gonic/gin"
"github.com/torkelo/grafana-pro/pkg/models"
)
type
authContext
struct
{
account
*
models
.
UserAccount
userAccount
*
models
.
UserAccount
}
func
(
auth
*
authContext
)
getAccountId
()
int
{
return
auth
.
account
.
Id
}
func
(
self
*
HttpServer
)
authDenied
(
c
*
gin
.
Context
)
{
c
.
Writer
.
Header
()
.
Set
(
"Location"
,
"/login"
)
c
.
Abort
(
302
)
}
func
(
self
*
HttpServer
)
auth
()
gin
.
HandlerFunc
{
return
func
(
c
*
gin
.
Context
)
{
session
,
_
:=
sessionStore
.
Get
(
c
.
Request
,
"grafana-session"
)
if
c
.
Request
.
URL
.
Path
!=
"/login"
&&
session
.
Values
[
"userAccountId"
]
==
nil
{
self
.
authDenied
(
c
)
return
}
account
,
err
:=
self
.
store
.
GetAccount
(
session
.
Values
[
"userAccountId"
]
.
(
int
))
if
err
!=
nil
{
self
.
authDenied
(
c
)
return
}
usingAccount
,
err
:=
self
.
store
.
GetAccount
(
session
.
Values
[
"usingAccountId"
]
.
(
int
))
if
err
!=
nil
{
self
.
authDenied
(
c
)
return
}
c
.
Set
(
"userAccount"
,
account
)
c
.
Set
(
"usingAccount"
,
usingAccount
)
session
.
Save
(
c
.
Request
,
c
.
Writer
)
}
}
pkg/api/api_dashboard.go
View file @
a9a06ad5
...
...
@@ -8,18 +8,17 @@ import (
func
init
()
{
addRoutes
(
func
(
self
*
HttpServer
)
{
self
.
router
.
GET
(
"/api/dashboards/:slug"
,
self
.
auth
()
,
self
.
getDashboard
)
self
.
router
.
GET
(
"/api/search/"
,
self
.
auth
()
,
self
.
search
)
self
.
router
.
POST
(
"/api/dashboard"
,
self
.
auth
()
,
self
.
postDashboard
)
self
.
router
.
DELETE
(
"/api/dashboard/:slug"
,
self
.
auth
()
,
self
.
deleteDashboard
)
self
.
addRoute
(
"GET"
,
"/api/dashboards/:slug"
,
self
.
getDashboard
)
self
.
addRoute
(
"GET"
,
"/api/search/"
,
self
.
search
)
self
.
addRoute
(
"POST"
,
"/api/dashboard/"
,
self
.
postDashboard
)
self
.
addRoute
(
"DELETE"
,
"/api/dashboard/:slug"
,
self
.
deleteDashboard
)
})
}
func
(
self
*
HttpServer
)
getDashboard
(
c
*
gin
.
Context
)
{
func
(
self
*
HttpServer
)
getDashboard
(
c
*
gin
.
Context
,
auth
*
authContext
)
{
slug
:=
c
.
Params
.
ByName
(
"slug"
)
accountId
,
err
:=
c
.
Get
(
"accountId"
)
dash
,
err
:=
self
.
store
.
GetDashboard
(
slug
,
a
ccountId
.
(
int
))
dash
,
err
:=
self
.
store
.
GetDashboard
(
slug
,
a
uth
.
getAccountId
(
))
if
err
!=
nil
{
c
.
JSON
(
404
,
newErrorResponse
(
"Dashboard not found"
))
return
...
...
@@ -30,17 +29,16 @@ func (self *HttpServer) getDashboard(c *gin.Context) {
c
.
JSON
(
200
,
dash
.
Data
)
}
func
(
self
*
HttpServer
)
deleteDashboard
(
c
*
gin
.
Context
)
{
func
(
self
*
HttpServer
)
deleteDashboard
(
c
*
gin
.
Context
,
auth
*
authContext
)
{
slug
:=
c
.
Params
.
ByName
(
"slug"
)
accountId
,
err
:=
c
.
Get
(
"accountId"
)
dash
,
err
:=
self
.
store
.
GetDashboard
(
slug
,
a
ccountId
.
(
int
))
dash
,
err
:=
self
.
store
.
GetDashboard
(
slug
,
a
uth
.
getAccountId
(
))
if
err
!=
nil
{
c
.
JSON
(
404
,
newErrorResponse
(
"Dashboard not found"
))
return
}
err
=
self
.
store
.
DeleteDashboard
(
slug
,
a
ccountId
.
(
int
))
err
=
self
.
store
.
DeleteDashboard
(
slug
,
a
uth
.
getAccountId
(
))
if
err
!=
nil
{
c
.
JSON
(
500
,
newErrorResponse
(
"Failed to delete dashboard: "
+
err
.
Error
()))
return
...
...
@@ -51,11 +49,10 @@ func (self *HttpServer) deleteDashboard(c *gin.Context) {
c
.
JSON
(
200
,
resp
)
}
func
(
self
*
HttpServer
)
search
(
c
*
gin
.
Context
)
{
func
(
self
*
HttpServer
)
search
(
c
*
gin
.
Context
,
auth
*
authContext
)
{
query
:=
c
.
Params
.
ByName
(
"q"
)
accountId
,
err
:=
c
.
Get
(
"accountId"
)
results
,
err
:=
self
.
store
.
Query
(
query
,
a
ccountId
.
(
int
))
results
,
err
:=
self
.
store
.
Query
(
query
,
a
uth
.
getAccountId
(
))
if
err
!=
nil
{
log
.
Error
(
"Store query error: %v"
,
err
)
c
.
JSON
(
500
,
newErrorResponse
(
"Failed"
))
...
...
@@ -65,15 +62,14 @@ func (self *HttpServer) search(c *gin.Context) {
c
.
JSON
(
200
,
results
)
}
func
(
self
*
HttpServer
)
postDashboard
(
c
*
gin
.
Context
)
{
func
(
self
*
HttpServer
)
postDashboard
(
c
*
gin
.
Context
,
auth
*
authContext
)
{
var
command
saveDashboardCommand
accountId
,
_
:=
c
.
Get
(
"accountId"
)
if
c
.
EnsureBody
(
&
command
)
{
dashboard
:=
models
.
NewDashboard
(
"test"
)
dashboard
.
Data
=
command
.
Dashboard
dashboard
.
Title
=
dashboard
.
Data
[
"title"
]
.
(
string
)
dashboard
.
AccountId
=
a
ccountId
.
(
int
)
dashboard
.
AccountId
=
a
uth
.
getAccountId
(
)
dashboard
.
UpdateSlug
()
if
dashboard
.
Data
[
"id"
]
!=
nil
{
...
...
pkg/api/api_login.go
View file @
a9a06ad5
...
...
@@ -35,8 +35,8 @@ func (self *HttpServer) loginPost(c *gin.Context) {
}
session
,
_
:=
sessionStore
.
Get
(
c
.
Request
,
"grafana-session"
)
session
.
Values
[
"
login"
]
=
loginModel
.
Email
session
.
Values
[
"
accountId"
]
=
account
.
Id
session
.
Values
[
"
userAccountId"
]
=
account
.
Id
session
.
Values
[
"
usingAccountId"
]
=
account
.
UsingAccount
Id
session
.
Save
(
c
.
Request
,
c
.
Writer
)
var
resp
=
&
LoginResultDto
{}
...
...
@@ -48,25 +48,8 @@ func (self *HttpServer) loginPost(c *gin.Context) {
func
(
self
*
HttpServer
)
logoutPost
(
c
*
gin
.
Context
)
{
session
,
_
:=
sessionStore
.
Get
(
c
.
Request
,
"grafana-session"
)
session
.
Values
[
"login"
]
=
nil
session
.
Values
=
nil
session
.
Save
(
c
.
Request
,
c
.
Writer
)
c
.
JSON
(
200
,
gin
.
H
{
"status"
:
"logged out"
})
}
func
(
self
*
HttpServer
)
auth
()
gin
.
HandlerFunc
{
return
func
(
c
*
gin
.
Context
)
{
session
,
_
:=
sessionStore
.
Get
(
c
.
Request
,
"grafana-session"
)
if
c
.
Request
.
URL
.
Path
!=
"/login"
&&
session
.
Values
[
"login"
]
==
nil
{
c
.
Writer
.
Header
()
.
Set
(
"Location"
,
"/login"
)
c
.
Abort
(
302
)
return
}
c
.
Set
(
"accountId"
,
session
.
Values
[
"accountId"
])
c
.
Set
(
"login"
,
session
.
Values
[
"login"
])
session
.
Save
(
c
.
Request
,
c
.
Writer
)
}
}
pkg/api/api_routing.go
0 → 100644
View file @
a9a06ad5
package
api
import
(
"github.com/gin-gonic/gin"
"github.com/torkelo/grafana-pro/pkg/models"
)
type
routeHandlerRegisterFn
func
(
self
*
HttpServer
)
type
routeHandlerFn
func
(
c
*
gin
.
Context
,
auth
*
authContext
)
var
routeHandlers
=
make
([]
routeHandlerRegisterFn
,
0
)
func
getRouteHandlerWrapper
(
handler
routeHandlerFn
)
gin
.
HandlerFunc
{
return
func
(
c
*
gin
.
Context
)
{
authContext
:=
authContext
{
account
:
c
.
MustGet
(
"usingAccount"
)
.
(
*
models
.
UserAccount
),
userAccount
:
c
.
MustGet
(
"userAccount"
)
.
(
*
models
.
UserAccount
),
}
handler
(
c
,
&
authContext
)
}
}
func
(
self
*
HttpServer
)
addRoute
(
method
string
,
path
string
,
handler
routeHandlerFn
)
{
switch
method
{
case
"GET"
:
self
.
router
.
GET
(
path
,
self
.
auth
(),
getRouteHandlerWrapper
(
handler
))
case
"POST"
:
self
.
router
.
POST
(
path
,
self
.
auth
(),
getRouteHandlerWrapper
(
handler
))
case
"DELETE"
:
self
.
router
.
DELETE
(
path
,
self
.
auth
(),
getRouteHandlerWrapper
(
handler
))
}
}
func
addRoutes
(
fn
routeHandlerRegisterFn
)
{
routeHandlers
=
append
(
routeHandlers
,
fn
)
}
pkg/models/account.go
0 → 100644
View file @
a9a06ad5
package
models
import
(
"errors"
"time"
)
type
CollaboratorLink
struct
{
AccountId
int
Role
string
ModifiedOn
time
.
Time
CreatedOn
time
.
Time
}
type
UserAccount
struct
{
Id
int
`gorethink:"id"`
UserName
string
Login
string
Email
string
Password
string
NextDashboardId
int
UsingAccountId
int
Collaborators
[]
CollaboratorLink
CreatedOn
time
.
Time
ModifiedOn
time
.
Time
}
func
(
account
*
UserAccount
)
AddCollaborator
(
accountId
int
)
error
{
for
_
,
collaborator
:=
range
account
.
Collaborators
{
if
collaborator
.
AccountId
==
accountId
{
return
errors
.
New
(
"Collaborator already exists"
)
}
}
account
.
Collaborators
=
append
(
account
.
Collaborators
,
CollaboratorLink
{
AccountId
:
accountId
,
Role
:
"admin"
,
CreatedOn
:
time
.
Now
(),
ModifiedOn
:
time
.
Now
(),
})
return
nil
}
pkg/models/dashboards.go
View file @
a9a06ad5
...
...
@@ -21,31 +21,6 @@ type Dashboard struct {
Data
map
[
string
]
interface
{}
}
type
CollaboratorLink
struct
{
AccountId
int
Role
string
ModifiedOn
time
.
Time
CreatedOn
time
.
Time
}
type
UserAccount
struct
{
Id
int
`gorethink:"id"`
UserName
string
Login
string
Email
string
Password
string
NextDashboardId
int
UsingAccountId
int
Collaborators
[]
CollaboratorLink
CreatedOn
time
.
Time
ModifiedOn
time
.
Time
}
type
UserContext
struct
{
UserId
string
AccountId
string
}
type
SearchResult
struct
{
Id
string
`json:"id"`
Title
string
`json:"title"`
...
...
@@ -87,12 +62,3 @@ func (dash *Dashboard) UpdateSlug() {
re2
:=
regexp
.
MustCompile
(
"
\\
s"
)
dash
.
Slug
=
re2
.
ReplaceAllString
(
re
.
ReplaceAllString
(
title
,
""
),
"-"
)
}
func
(
account
*
UserAccount
)
AddCollaborator
(
accountId
int
)
{
account
.
Collaborators
=
append
(
account
.
Collaborators
,
CollaboratorLink
{
AccountId
:
accountId
,
Role
:
"admin"
,
CreatedOn
:
time
.
Now
(),
ModifiedOn
:
time
.
Now
(),
})
}
pkg/stores/rethinkdb_accounts.go
View file @
a9a06ad5
...
...
@@ -32,6 +32,7 @@ func (self *rethinkStore) SaveUserAccount(account *models.UserAccount) error {
}
account
.
Id
=
accountId
account
.
UsingAccountId
=
accountId
resp
,
err
:=
r
.
Table
(
"accounts"
)
.
Insert
(
account
)
.
RunWrite
(
self
.
session
)
if
err
!=
nil
{
...
...
views/index.html
View file @
a9a06ad5
...
...
@@ -28,9 +28,14 @@
<div
ng-include=
"'app/partials/pro/sidemenu.html'"
></div>
</aside>
<div
ng-repeat=
'alert in dashAlerts.list'
class=
"alert-{{alert.severity}} dashboard-notice"
ng-show=
"$last"
>
<button
type=
"button"
class=
"close"
ng-click=
"dashAlerts.clear(alert)"
style=
"padding-right:50px"
>
×
</button>
<strong>
{{alert.title}}
</strong>
<span
ng-bind-html=
'alert.text'
></span>
<div
style=
"padding-right:10px"
class=
'pull-right small'
>
{{$index + 1}} alert(s)
</div>
<div
class=
"page-alert-list"
>
<div
ng-repeat=
'alert in dashAlerts.list'
class=
"alert-{{alert.severity}} alert"
>
<button
type=
"button"
class=
"alert-close"
ng-click=
"dashAlerts.clear(alert)"
>
<i
class=
"icon-remove-sign"
></i>
</button>
<div
class=
"alert-title"
>
{{alert.title}}
</div>
<div
ng-bind-html=
'alert.text'
></div>
</div>
</div>
<div
ng-view
class=
"pro-main-view"
ng-class=
"{'dashboard-fullscreen': fullscreen}"
></div>
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment