Skip to content

Commit

Permalink
Support TiDB Authentication (#70)
Browse files Browse the repository at this point in the history
Signed-off-by: Breezewish <me@breeswish.org>
  • Loading branch information
breezewish authored Feb 23, 2020
1 parent 9563421 commit a47c468
Show file tree
Hide file tree
Showing 50 changed files with 1,594 additions and 288 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
.env
/bin

# Binaries for programs and plugins
Expand Down
1 change: 0 additions & 1 deletion .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,4 @@ linters:
- depguard
- prealloc
- scopelint
- gocritic
- whitespace
30 changes: 30 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -153,3 +153,33 @@ If you want to develop Dashboard UI, the recommended workflow is as follows:
Currently the development server will not watch for Golang code changes, which means you must
manually rebuild the Dashboard API Client if back-end code is updated (for example, you pulled
latest change from the repository).

## For Developers How To ...

### Keep session valid after rebooting the server

By default, the session secret key is generated dynamically when the server starts. This results in invalidating
your previously acquired session token. For easier development, you can supply a fixed session secret key by
setting `DASHBOARD_SESSION_SECRET` in the environment variable or in `.env` file like:

```env
DASHBOARD_SESSION_SECRET=aaaaaaaaaabbbbbbbbbbccccccccccdd
```

The supplied secret key must be 32 bytes, otherwise it will not be effective.

Note: the maximum lifetime of a token is 24 hours by default, so you still need to acquire token every 24 hours.

### Supply session token in the Swagger UI

1. Acquire a token first through `/user/login` in the Swagger UI.

2. Click the "Authorize" button in the Swagger UI, set value to `Bearer xxxx` where `xxxx` is the token you acquired
in step 1.

<img src="etc/readme_howto_swagger_session.jpg" width="400">

### Release new UI assets

Simply modify `ui/.github_release_version`. The assets will be released automatically after your change is merged
to master.
28 changes: 19 additions & 9 deletions cmd/tidb-dashboard/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@
// @license.name Apache 2.0
// @license.url http://www.apache.org/licenses/LICENSE-2.0.html
// @BasePath /dashboard/api
// @securityDefinitions.apikey JwtAuth
// @in header
// @name Authorization

package main

Expand All @@ -31,6 +34,7 @@ import (
"sync"
"syscall"

"github.com/joho/godotenv"
"github.com/pingcap/log"
"go.etcd.io/etcd/clientv3"
"go.uber.org/zap"
Expand All @@ -43,12 +47,12 @@ import (
keyvisualregion "github.com/pingcap-incubator/tidb-dashboard/pkg/keyvisual/region"
"github.com/pingcap-incubator/tidb-dashboard/pkg/pd"
"github.com/pingcap-incubator/tidb-dashboard/pkg/swaggerserver"
"github.com/pingcap-incubator/tidb-dashboard/pkg/tidb"
"github.com/pingcap-incubator/tidb-dashboard/pkg/uiserver"
"github.com/pingcap-incubator/tidb-dashboard/pkg/utils"
)

type DashboardCLIConfig struct {
Version bool
ListenHost string
ListenPort int
CoreConfig *config.Config
Expand All @@ -61,10 +65,10 @@ type DashboardCLIConfig struct {
func NewCLIConfig() *DashboardCLIConfig {
cfg := &DashboardCLIConfig{}
cfg.CoreConfig = &config.Config{}
cfg.CoreConfig.Version = utils.ReleaseVersion

flag.BoolVar(&cfg.Version, "V", false, "Print version information and exit")
flag.BoolVar(&cfg.Version, "version", false, "Print version information and exit")
var showVersion bool
flag.BoolVar(&showVersion, "v", false, "Print version information and exit")
flag.BoolVar(&showVersion, "version", false, "Print version information and exit")
flag.StringVar(&cfg.ListenHost, "host", "0.0.0.0", "The listen address of the Dashboard Server")
flag.IntVar(&cfg.ListenPort, "port", 12333, "The listen port of the Dashboard Server")
flag.StringVar(&cfg.CoreConfig.DataDir, "data-dir", "/tmp/dashboard-data", "Path to the Dashboard Server data directory")
Expand All @@ -76,7 +80,7 @@ func NewCLIConfig() *DashboardCLIConfig {

flag.Parse()

if cfg.Version {
if showVersion {
utils.PrintInfo()
exit(0)
}
Expand Down Expand Up @@ -111,6 +115,8 @@ func getContext() (context.Context, *sync.WaitGroup) {
}

func main() {
_ = godotenv.Load()

// Flushing any buffered log entries
defer log.Sync() //nolint:errcheck

Expand All @@ -121,6 +127,10 @@ func main() {
defer store.Close() //nolint:errcheck

etcdClient := pd.NewEtcdClient(cliConfig.CoreConfig)
tidbForwarder := tidb.NewForwarder(tidb.NewForwarderConfig(), etcdClient)
// FIXME: Handle open error
tidbForwarder.Open() //nolint:errcheck
defer tidbForwarder.Close() //nolint:errcheck

// key visual
remoteDataProvider := &keyvisualregion.PDDataProvider{
Expand All @@ -136,8 +146,9 @@ func main() {
keyvisualService.Start()

services := &apiserver.Services{
Store: store,
KeyVisual: keyvisualService,
Store: store,
KeyVisual: keyvisualService,
TiDBForwarder: tidbForwarder,
}
mux := http.DefaultServeMux
mux.Handle("/dashboard/", http.StripPrefix("/dashboard", uiserver.Handler()))
Expand All @@ -147,9 +158,8 @@ func main() {
listenAddr := fmt.Sprintf("%s:%d", cliConfig.ListenHost, cliConfig.ListenPort)
listener, err := net.Listen("tcp", listenAddr)
if err != nil {
log.Fatal("Dashboard server listen failed", zap.String("addr", listenAddr), zap.Error(err))
store.Close() //nolint:errcheck
exit(1)
log.Fatal("Dashboard server listen failed", zap.String("addr", listenAddr), zap.Error(err))
}

utils.LogInfo()
Expand Down
Binary file added etc/readme_howto_swagger_session.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,16 @@ go 1.13

require (
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751
github.com/appleboy/gin-jwt/v2 v2.6.3
github.com/elazarl/go-bindata-assetfs v1.0.0
github.com/gin-contrib/gzip v0.0.1
github.com/gin-gonic/gin v1.5.0
github.com/go-bindata/go-bindata v3.1.2+incompatible
github.com/go-sql-driver/mysql v1.4.1
github.com/gtank/cryptopasta v0.0.0-20170601214702-1f550f6f2f69
github.com/jinzhu/gorm v1.9.12
github.com/joho/godotenv v1.3.0
github.com/joomcode/errorx v1.0.1
github.com/pingcap/check v0.0.0-20191216031241-8a5a85928f12
github.com/pingcap/log v0.0.0-20200117041106-d28c14d3b1cd
github.com/pkg/errors v0.9.1
Expand Down
19 changes: 19 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuy
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/appleboy/gin-jwt/v2 v2.6.3 h1:aK4E3DjihWEBUTjEeRnGkA5nUkmwJPL1CPonMa2usRs=
github.com/appleboy/gin-jwt/v2 v2.6.3/go.mod h1:MfPYA4ogzvOcVkRwAxT7quHOtQmVKDpTwxyUrC2DNw0=
github.com/appleboy/gofight/v2 v2.1.2 h1:VOy3jow4vIK8BRQJoC/I9muxyYlJ2yb9ht2hZoS3rf4=
github.com/appleboy/gofight/v2 v2.1.2/go.mod h1:frW+U1QZEdDgixycTj4CygQ48yLTUhplt43+Wczp3rw=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0 h1:HWo1m869IqiPhD389kmkxeTalrjNbbJTC8LXupb+sl0=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
Expand Down Expand Up @@ -115,6 +119,8 @@ github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92Bcuy
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
github.com/grpc-ecosystem/grpc-gateway v1.9.5 h1:UImYN5qQ8tuGpGE16ZmjvcTtTw24zw1QAp/SlnNrZhI=
github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
github.com/gtank/cryptopasta v0.0.0-20170601214702-1f550f6f2f69 h1:7xsUJsB2NrdcttQPa7JLEaGzvdbk7KvfrjgHZXOQRo0=
github.com/gtank/cryptopasta v0.0.0-20170601214702-1f550f6f2f69/go.mod h1:YLEMZOtU+AZ7dhN9T/IpGhXVGly2bvkJQ+zxj3WeVQo=
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/jinzhu/gorm v1.9.12 h1:Drgk1clyWT9t9ERbzHza6Mj/8FY/CqMyVzOiHviMo6Q=
Expand All @@ -123,8 +129,12 @@ github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
github.com/jinzhu/now v1.0.1 h1:HjfetcXq097iXP0uoPCdnM4Efp5/9MsM0/M+XOTeR3M=
github.com/jinzhu/now v1.0.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc=
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
github.com/jonboulle/clockwork v0.1.0 h1:VKV+ZcuP6l3yW9doeqz6ziZGgcynBVQO+obU0+0hcPo=
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
github.com/joomcode/errorx v1.0.1 h1:CalpDWz14ZHd68fIqluJasJosAewpz2TFaJALrUxjrk=
github.com/joomcode/errorx v1.0.1/go.mod h1:kgco15ekB6cs+4Xjzo7SPeXzx38PbJzBwbnu9qfVNHQ=
github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.7 h1:KfgG9LzI+pYjr4xvmz/5H4FXjokeP+rlHLhv3iH62Fo=
Expand Down Expand Up @@ -233,6 +243,12 @@ github.com/swaggo/swag v1.5.1/go.mod h1:1Bl9F/ZBpVWh22nY0zmYyASPO1lI/zIwRDrpZU+t
github.com/swaggo/swag v1.6.3/go.mod h1:wcc83tB4Mb2aNiL/HP4MFeQdpHUrca+Rp/DRNgWAUio=
github.com/swaggo/swag v1.6.5 h1:2C+t+xyK6p1sujqncYO/VnMvPZcBJjNdKKyxbOdAW8o=
github.com/swaggo/swag v1.6.5/go.mod h1:Y7ZLSS0d0DdxhWGVhQdu+Bu1QhaF5k0RD7FKdiAykeY=
github.com/tidwall/gjson v1.3.5 h1:2oW9FBNu8qt9jy5URgrzsVx/T/KSn3qn/smJQ0crlDQ=
github.com/tidwall/gjson v1.3.5/go.mod h1:P256ACg0Mn+j1RXIDXoss50DeIABTYK1PULOJHhxOls=
github.com/tidwall/match v1.0.1 h1:PnKP62LPNxHKTwvHHZZzdOAOCtsJTjo6dZLCwpKm5xc=
github.com/tidwall/match v1.0.1/go.mod h1:LujAq0jyVjBy028G1WhWfIzbpQfMO8bBZ6Tyb0+pL9E=
github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4=
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8 h1:ndzgwNDnKIqyCvHTXaCqh9KlOWKvBry6nuXMJmonVsE=
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
Expand Down Expand Up @@ -334,6 +350,7 @@ golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtn
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191107010934-f79515f33823 h1:akkRBeitX2EZP59KdtKw310CI4WGPCNPyrLbE7WZA8Y=
golang.org/x/tools v0.0.0-20191107010934-f79515f33823/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7 h1:9zdDQZ7Thm29KFXgAX/+yaf3eVbP7djjWp/dXAppNCc=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508=
Expand Down Expand Up @@ -361,6 +378,8 @@ gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bl
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.7 h1:VUgggvou5XRW9mHwD/yXxIYSMtY0zoKQf/v226p2nyo=
gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM=
Expand Down
18 changes: 13 additions & 5 deletions pkg/apiserver/apiserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,20 @@ import (

"github.com/pingcap-incubator/tidb-dashboard/pkg/apiserver/foo"
"github.com/pingcap-incubator/tidb-dashboard/pkg/apiserver/info"
"github.com/pingcap-incubator/tidb-dashboard/pkg/apiserver/user"
"github.com/pingcap-incubator/tidb-dashboard/pkg/apiserver/utils"
"github.com/pingcap-incubator/tidb-dashboard/pkg/config"
"github.com/pingcap-incubator/tidb-dashboard/pkg/dbstore"
"github.com/pingcap-incubator/tidb-dashboard/pkg/keyvisual"
"github.com/pingcap-incubator/tidb-dashboard/pkg/tidb"
)

var once sync.Once

type Services struct {
Store *dbstore.DB
KeyVisual *keyvisual.Service
Store *dbstore.DB
TiDBForwarder *tidb.Forwarder
KeyVisual *keyvisual.Service
}

func Handler(apiPrefix string, config *config.Config, services *Services) http.Handler {
Expand All @@ -45,12 +49,16 @@ func Handler(apiPrefix string, config *config.Config, services *Services) http.H
r.Use(cors.AllowAll())
r.Use(gin.Recovery())
r.Use(gzip.Gzip(gzip.BestSpeed))
r.Use(utils.MWHandleErrors())

endpoint := r.Group(apiPrefix)

foo.NewService(config).Register(endpoint)
info.NewService(config, services.Store).Register(endpoint)
services.KeyVisual.Register(endpoint)
auth := user.NewAuthService(services.TiDBForwarder)
auth.Register(endpoint)

foo.NewService(config).Register(endpoint, auth)
info.NewService(config, services.TiDBForwarder, services.Store).Register(endpoint, auth)
services.KeyVisual.Register(endpoint, auth)

return r
}
8 changes: 7 additions & 1 deletion pkg/apiserver/foo/foo.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ import (

"github.com/gin-gonic/gin"

"github.com/pingcap-incubator/tidb-dashboard/pkg/apiserver/user"
// Import for swag go doc
_ "github.com/pingcap-incubator/tidb-dashboard/pkg/apiserver/utils"
"github.com/pingcap-incubator/tidb-dashboard/pkg/config"
)

Expand All @@ -28,8 +31,9 @@ func NewService(config *config.Config) *Service {
return &Service{}
}

func (s *Service) Register(r *gin.RouterGroup) {
func (s *Service) Register(r *gin.RouterGroup, auth *user.AuthService) {
endpoint := r.Group("/foo")
endpoint.Use(auth.MWAuthRequired())
endpoint.GET("/:name", s.greetHandler)
}

Expand All @@ -40,6 +44,8 @@ func (s *Service) Register(r *gin.RouterGroup) {
// @Param name path string true "Name"
// @Success 200 {string} string
// @Router /foo/{name} [get]
// @Security JwtAuth
// @Failure 401 {object} utils.APIError "Unauthorized failure"
func (s *Service) greetHandler(c *gin.Context) {
name := c.Param("name")
c.String(http.StatusOK, "Hello %s", name)
Expand Down
77 changes: 63 additions & 14 deletions pkg/apiserver/info/info.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,39 +17,88 @@ import (
"net/http"

"github.com/gin-gonic/gin"
"github.com/jinzhu/gorm"

"github.com/pingcap-incubator/tidb-dashboard/pkg/apiserver/user"
"github.com/pingcap-incubator/tidb-dashboard/pkg/apiserver/utils"
"github.com/pingcap-incubator/tidb-dashboard/pkg/config"
"github.com/pingcap-incubator/tidb-dashboard/pkg/dbstore"
"github.com/pingcap-incubator/tidb-dashboard/pkg/tidb"
utils2 "github.com/pingcap-incubator/tidb-dashboard/pkg/utils"
)

type Info struct {
Version string `json:"version"`
PDEndPoint string `json:"pd_end_point"`
}

type Service struct {
config *config.Config
db *dbstore.DB
config *config.Config
db *dbstore.DB
tidbForwarder *tidb.Forwarder
}

func NewService(config *config.Config, db *dbstore.DB) *Service {
return &Service{config: config, db: db}
func NewService(config *config.Config, tidbForwarder *tidb.Forwarder, db *dbstore.DB) *Service {
return &Service{config: config, db: db, tidbForwarder: tidbForwarder}
}

func (s *Service) Register(r *gin.RouterGroup) {
func (s *Service) Register(r *gin.RouterGroup, auth *user.AuthService) {
endpoint := r.Group("/info")
endpoint.Use(auth.MWAuthRequired())
endpoint.GET("/info", s.infoHandler)
endpoint.GET("/whoami", s.whoamiHandler)
endpoint.GET("/databases", utils.MWConnectTiDB(s.tidbForwarder), s.databasesHandler)
}

type InfoResponse struct { //nolint:golint
Version utils2.VersionInfo `json:"version"`
PDEndPoint string `json:"pd_end_point"`
}

// @Summary Dashboard info
// @Description Get information about the dashboard service.
// @ID getInfo
// @Produce json
// @Success 200 {object} Info
// @Success 200 {object} InfoResponse
// @Router /info/info [get]
// @Security JwtAuth
// @Failure 401 {object} utils.APIError "Unauthorized failure"
func (s *Service) infoHandler(c *gin.Context) {
info := Info{
Version: s.config.Version,
resp := InfoResponse{
Version: utils2.GetVersionInfo(),
PDEndPoint: s.config.PDEndPoint,
}
c.JSON(http.StatusOK, info)
c.JSON(http.StatusOK, resp)
}

type WhoAmIResponse struct {
Username string `json:"username"`
}

// @Summary Current login
// @Description Get current login session
// @Produce json
// @Success 200 {object} WhoAmIResponse
// @Router /info/whoami [get]
// @Security JwtAuth
// @Failure 401 {object} utils.APIError "Unauthorized failure"
func (s *Service) whoamiHandler(c *gin.Context) {
sessionUser := c.MustGet(utils.SessionUserKey).(*utils.SessionUser)
resp := WhoAmIResponse{Username: sessionUser.TiDBUsername}
c.JSON(http.StatusOK, resp)
}

type DatabaseResponse = []string

// @Summary Example: Get all databases
// @Description Get all databases.
// @Produce json
// @Success 200 {object} DatabaseResponse
// @Router /info/databases [get]
// @Security JwtAuth
// @Failure 401 {object} utils.APIError "Unauthorized failure"
func (s *Service) databasesHandler(c *gin.Context) {
db := c.MustGet(utils.TiDBConnectionKey).(*gorm.DB)
var result DatabaseResponse
err := db.Raw("show databases").Pluck("Databases", &result).Error
if err != nil {
_ = c.Error(err)
return
}
c.JSON(http.StatusOK, result)
}
Loading

0 comments on commit a47c468

Please sign in to comment.