Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add external URL endpoint options for the console (close #2824) #3570

Closed
wants to merge 31 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
159c815
remove admin secret key
ashishra0 Dec 18, 2019
f509df7
add check for admin secret
ashishra0 Dec 18, 2019
de41f3c
run make assets
ashishra0 Dec 19, 2019
71dacad
add check for admin secret
ashishra0 Dec 19, 2019
b098e9c
Add two external endpoint flag
ashishra0 Dec 19, 2019
2d7718d
remove conditional check for console mode
ashishra0 Dec 19, 2019
6fb6cff
update version
ashishra0 Dec 19, 2019
c2d9e31
Merge branch 'master' into console-issue-2824
shahidhk Dec 25, 2019
86674ec
refactors to use sensible flags
shahidhk Dec 25, 2019
d4adf15
handle unauthorized request
ashishra0 Dec 26, 2019
320050c
merge remote changes
ashishra0 Dec 26, 2019
2902c5d
Merge branch 'master' into console-issue-2824
shahidhk Dec 26, 2019
85b56f3
refactor http message
ashishra0 Dec 26, 2019
9072a91
merge remote changes
ashishra0 Dec 26, 2019
fa0be03
Merge branch 'master' into console-issue-2824
rikinsk Jan 16, 2020
1957eed
Merge branch 'master' into console-issue-2824
rikinsk Jan 21, 2020
658ccc6
Merge branch 'master' into console-issue-2824
rikinsk Mar 20, 2020
d7e34c6
Update console.go
rikinsk Mar 20, 2020
2370888
Update test console script and readme
Mar 26, 2020
db520a1
update cli console.htmls
rikinsk Mar 27, 2020
d30dba1
Merge branch 'master' into console-issue-2824
rikinsk Mar 27, 2020
83d3a0d
Update README.md
rikinsk Mar 27, 2020
fa60bb4
Merge branch 'master' into console-issue-2824
rikinsk Mar 30, 2020
8bf3cde
Merge remote-tracking branch 'hq-origin/master' into console-issue-2824
Jul 8, 2020
72c8b03
[skip ci] re-add the changes to the cli files
Jul 14, 2020
e13305d
remove unreachable code
Jul 15, 2020
fc901c0
change console.go with 4 FIXME
Jul 15, 2020
8c0ccf6
migrate console changes
Jul 15, 2020
f4e6b4b
Merge branch 'master' into console-issue-2824
Jul 15, 2020
2628b63
run make assets
Jul 15, 2020
a146d85
run format and lint
Jul 15, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions .circleci/test-console.sh
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,7 @@ wait_for_port 9693
export PORT=3000
export NODE_ENV=development
export DATA_API_URL=http://localhost:8080
export API_HOST=http://localhost
export API_PORT=9693
export MIGRATE_API_URL=http://localhost:9693
export CONSOLE_MODE=cli
export DEV_DATA_API_URL=http://localhost:8080
export URL_PREFIX=/
Expand Down
1 change: 0 additions & 1 deletion cli/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -719,7 +719,6 @@ func (ec *ExecutionContext) readConfig() error {
return errors.Wrap(err, "setting up TLS config failed")
}
return ec.Config.ServerConfig.SetHTTPClient()
return nil
}

// setupSpinner creates a default spinner if the context does not already have
Expand Down
164 changes: 158 additions & 6 deletions cli/commands/console.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
package commands

import (
"net/http"
"os"
"sync"

"github.com/gin-contrib/cors"
"github.com/gin-contrib/static"
"github.com/hasura/graphql-engine/cli/migrate"
"github.com/hasura/graphql-engine/cli/migrate/api"
"github.com/hasura/graphql-engine/cli/util"
"github.com/sirupsen/logrus"

"github.com/gin-gonic/gin"
"github.com/hasura/graphql-engine/cli"
Expand Down Expand Up @@ -55,7 +61,9 @@ func NewConsoleCmd(ec *cli.ExecutionContext) *cobra.Command {

f.StringVar(&opts.APIPort, "api-port", "9693", "port for serving migrate api")
f.StringVar(&opts.ConsolePort, "console-port", "9695", "port for serving console")
f.StringVar(&opts.Address, "address", "localhost", "address to serve console and migration API from")
f.StringVar(&opts.Address, "address", "localhost", "address to serve console and migrate api from")
f.StringVar(&opts.ServerExternalEndpoint, "server-external-endpoint", "", "endpoint using which console can access graphql engine")
f.StringVar(&opts.CliExternalEndpoint, "cli-external-endpoint", "", "endpoint using which console can access the migrate api served by cli")
f.BoolVar(&opts.DontOpenBrowser, "no-browser", false, "do not automatically open console in browser")
f.StringVar(&opts.StaticDir, "static-dir", "", "directory where static assets mentioned in the console html template can be served from")
f.StringVar(&opts.Browser, "browser", "", "open console in a specific browser")
Expand All @@ -81,11 +89,12 @@ func NewConsoleCmd(ec *cli.ExecutionContext) *cobra.Command {
type ConsoleOptions struct {
EC *cli.ExecutionContext

APIPort string
ConsolePort string
Address string

DontOpenBrowser bool
APIPort string
ConsolePort string
Address string
ServerExternalEndpoint string
CliExternalEndpoint string
DontOpenBrowser bool

WG *sync.WaitGroup

Expand Down Expand Up @@ -113,6 +122,26 @@ func (o *ConsoleOptions) Run() error {
templateProvider := console.NewDefaultTemplateProvider(basePath, templateFilename)
consoleTemplateVersion := templateProvider.GetTemplateVersion(o.EC.Version)
consoleAssetsVersion := templateProvider.GetAssetsVersion(o.EC.Version)

if o.CliExternalEndpoint == "" {
o.CliExternalEndpoint = "http://" + o.Address + ":" + o.APIPort
}
if o.ServerExternalEndpoint == "" {
o.ServerExternalEndpoint = o.EC.Config.ServerConfig.Endpoint
}

// FIXME: My Router struct
r := &cRouter{
g,
t,
}
Comment on lines +133 to +137
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@scriptonist I'm marking 4 FIXME comments that I need help with. Basically wanted to know if there are alternate structures or methods that need to be used in order to get this PR up to speed.


r.router.Use(verifyAdminSecret())
r.setRoutes(o.EC.MigrationDir, o.EC.Logger)

// consoleTemplateVersion := o.EC.Version.GetConsoleTemplateVersion()
// consoleAssetsVersion := o.EC.Version.GetConsoleAssetsVersion()

o.EC.Logger.Debugf("rendering console template [%s] with assets [%s]", consoleTemplateVersion, consoleAssetsVersion)

adminSecretHeader := cli.GetAdminSecretHeaderName(o.EC.Version)
Expand Down Expand Up @@ -171,3 +200,126 @@ func (o *ConsoleOptions) Run() error {

return console.Serve(serveOpts)
}

func verifyAdminSecret() gin.HandlerFunc {
return func(c *gin.Context) {
if ec.Config.ServerConfig.AdminSecret != "" {
if c.GetHeader(cli.XHasuraAdminSecret) != ec.Config.ServerConfig.AdminSecret {
//reject
c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"message": "unauthorized"})
}
}
}
}

type cRouter struct {
router *gin.Engine
migrate *migrate.Migrate
}

func (r *cRouter) setRoutes(migrationDir string, logger *logrus.Logger) {
apis := r.router.Group("/apis")
{
apis.Use(setLogger(logger))
apis.Use(setFilePath(migrationDir))
apis.Use(setMigrate(r.migrate))
apis.Use(setConfigVersion())
// Migrate api endpoints and middleware
migrateAPIs := apis.Group("/migrate")
{
settingsAPIs := migrateAPIs.Group("/settings")
{
settingsAPIs.Any("", api.SettingsAPI)
}
squashAPIs := migrateAPIs.Group("/squash")
{
squashAPIs.POST("/create", api.SquashCreateAPI)
squashAPIs.POST("/delete", api.SquashDeleteAPI)
}
migrateAPIs.Any("", api.MigrateAPI)
}
// Migrate api endpoints and middleware
metadataAPIs := apis.Group("/metadata")
{
metadataAPIs.Any("", api.MetadataAPI)
}
}
}

func setMigrate(t *migrate.Migrate) gin.HandlerFunc {
return func(c *gin.Context) {
c.Set("migrate", t)
c.Next()
}
}

func setFilePath(dir string) gin.HandlerFunc {
return func(c *gin.Context) {
// FIXME
host := getFilePath(dir)
c.Set("filedir", host)
c.Next()
Comment on lines +258 to +261
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The last one

}
}

func setConfigVersion() gin.HandlerFunc {
return func(c *gin.Context) {
c.Set("version", int(ec.Config.Version))
c.Next()
}
}

func setMetadataFile(file string) gin.HandlerFunc {
return func(c *gin.Context) {
c.Set("metadataFile", file)
c.Next()
}
}

func setLogger(logger *logrus.Logger) gin.HandlerFunc {
return func(c *gin.Context) {
c.Set("logger", logger)
c.Next()
}
}

func allowCors() gin.HandlerFunc {
config := cors.DefaultConfig()
config.AddAllowHeaders("X-Hasura-User-Id")
config.AddAllowHeaders(cli.XHasuraAccessKey)
config.AddAllowHeaders(cli.XHasuraAdminSecret)
config.AddAllowHeaders("X-Hasura-Role")
config.AddAllowHeaders("X-Hasura-Allowed-Roles")
config.AddAllowMethods("DELETE")
config.AllowAllOrigins = true
config.AllowCredentials = false
return cors.New(config)
}

func serveConsole(assetsVersion, staticDir string, opts gin.H) (*gin.Engine, error) {
// An Engine instance with the Logger and Recovery middleware already attached.
r := gin.New()

// FIXME: DoAssetExist
if !util.DoAssetExist("assets/" + assetsVersion + "/console.html") {
assetsVersion = "latest"
}
Comment on lines +303 to +306
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Second one.


// Template console.html
// FIXME: LoadTemplates
templateRender, err := util.LoadTemplates("assets/"+assetsVersion+"/", "console.html")
Comment on lines +309 to +310
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Third one

if err != nil {
return nil, errors.Wrap(err, "cannot fetch template")
}
r.HTMLRender = templateRender

if staticDir != "" {
r.Use(static.Serve("/static", static.LocalFile(staticDir, false)))
opts["cliStaticDir"] = staticDir
}
r.GET("/*action", func(c *gin.Context) {
c.HTML(http.StatusOK, "console.html", &opts)
})

return r, nil
}
2 changes: 1 addition & 1 deletion cli/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ require (
github.com/jinzhu/gorm v1.9.11 // indirect
github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0
github.com/manifoldco/promptui v0.6.0
github.com/markbates/pkger v0.15.1
github.com/markbates/pkger v0.17.0
github.com/mattn/go-colorable v0.1.4
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b
github.com/microcosm-cc/bluemonday v1.0.2 // indirect
Expand Down
4 changes: 2 additions & 2 deletions cli/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -211,8 +211,8 @@ github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzR
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/manifoldco/promptui v0.6.0 h1:GuXmIdl5lhlamnWf3NbsKWYlaWyHABeStbD1LLsQMuA=
github.com/manifoldco/promptui v0.6.0/go.mod h1:o9/C5VV8IPXxjxpl9au84MtQGIi5dwn7eldAgEdePPs=
github.com/markbates/pkger v0.15.1 h1:3MPelV53RnGSW07izx5xGxl4e/sdRD6zqseIk0rMASY=
github.com/markbates/pkger v0.15.1/go.mod h1:0JoVlrol20BSywW79rN3kdFFsE5xYM+rSCQDXbLhiuI=
github.com/markbates/pkger v0.17.0 h1:RFfyBPufP2V6cddUyyEVSHBpaAnM1WzaMNyqomeT+iY=
github.com/markbates/pkger v0.17.0/go.mod h1:0JoVlrol20BSywW79rN3kdFFsE5xYM+rSCQDXbLhiuI=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA=
Expand Down
9 changes: 3 additions & 6 deletions cli/pkg/console/templates/gohtml/latest/console.gohtml
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,19 @@
<head>
<script>
window.__env = {
apiHost: {{.apiHost}},
apiPort: "{{.apiPort}}",
cliVersion: {{.cliVersion}},
dataApiUrl: {{.dataApiUrl}},
dataApiVersion: {{.dataApiVersion}},
{{- if .hasAccessKey }}
accessKey: {{.adminSecret}},
{{ else }}
adminSecret: {{.adminSecret}},
{{- if .isAdminSecretSet }}
isAdminSecretSet: {{.isAdminSecretSet}},
{{ end -}}
urlPrefix: {{.urlPrefix}},
consoleMode: "cli",
cliUUID: {{.cliUUID}},
enableTelemetry: {{.enableTelemetry}},
assetsPath:"https://graphql-engine-cdn.hasura.io/console/assets",
serverVersion: "{{.serverVersion}}",
migrateApiUrl: {{.migrateApiUrl}},
migrateSkipExecution: {{.migrateSkipExecution}},
cdnAssets: {{.cdnAssets}},
assetsVersion: {{.assetsVersion}},
Expand Down
9 changes: 3 additions & 6 deletions cli/pkg/console/templates/gohtml/unversioned/console.gohtml
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,19 @@
<head>
<script>
window.__env = {
apiHost: {{.apiHost}},
apiPort: "{{.apiPort}}",
cliVersion: {{.cliVersion}},
dataApiUrl: {{.dataApiUrl}},
dataApiVersion: {{.dataApiVersion}},
{{- if .hasAccessKey }}
accessKey: {{.adminSecret}},
{{ else }}
adminSecret: {{.adminSecret}},
{{- if .isAdminSecretSet }}
isAdminSecretSet: {{.isAdminSecretSet}},
{{ end -}}
urlPrefix: {{.urlPrefix}},
consoleMode: "cli",
cliUUID: {{.cliUUID}},
enableTelemetry: {{.enableTelemetry}},
assetsPath:"https://graphql-engine-cdn.hasura.io/console/assets",
serverVersion: "{{.serverVersion}}",
migrateApiUrl: {{.migrateApiUrl}},
migrateSkipExecution: {{.migrateSkipExecution}},
cdnAssets: {{.cdnAssets}},
assetsVersion: {{.assetsVersion}},
Expand Down
6 changes: 4 additions & 2 deletions cli/pkg/console/templates/packed/pkged.go

Large diffs are not rendered by default.

10 changes: 4 additions & 6 deletions console/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,7 @@ Environment variables accepted in `cli` mode:

- `NODE_ENV`: Console build environment (`development`/`production`)
- `PORT`: The port where Hasura console will run locally
- `API_HOST`: Hasura CLI host. Hasura CLI runs on `http://localhost` by default.
- `API_PORT`: Hasura CLI port. Hasura CLI exposes the API at `9693` by default
- `MIGRATE_API_URL`: CLI Migrate API URL, `http://localhost:9693` by default.
- `CDN_ASSETS`: Should assets be loaded from CDN (`true`/`false`)
- `ASSETS_PATH`: Path to console assets
- `ASSETS_VERSION`: Version of console assets being served
Expand All @@ -109,15 +108,14 @@ Environment variables accepted in `cli` mode:
- `DATA_API_URL`: The Hasura GraphQL engine url. (If you are running it on Heroku, it will look like <app-name\>.herokuapp.com, if you are running locally, it will look like http://localhost:<port\>)
- `SERVER_VERSION`: Hasura GraphQL Engine server version
- `CONSOLE_MODE`: In cli mode, it should be `cli`
- `ADMIN_SECRET`: the admin secret passed via the CLI
- `IS_ADMIN_SECRET_SET`: Is GraphQl engine configured with an admin secret (`true`/`false`)

Here's an example `.env` file for `cli` mode:

```bash
NODE_ENV=development
PORT=3000
API_HOST=http://localhost
API_PORT=9693
MIGRATE_API_URL=http://localhost:9693
CDN_ASSETS=true
ASSETS_PATH=https://graphql-engine-cdn.hasura.io/console/assets
ASSETS_VERSION=channel/stable/v1.0
Expand All @@ -126,7 +124,7 @@ URL_PREFIX=/
DATA_API_URL=http://localhost:8080
SERVER_VERSION=v1.0.0
CONSOLE_MODE=cli
ADMIN_SECRET=my-admin-secret
IS_ADMIN_SECRET_SET=true
```

##### Run console development server:
Expand Down
6 changes: 3 additions & 3 deletions console/src/Endpoints.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import globals from './Globals';

const baseUrl = globals.dataApiUrl;
const hasuractlApiHost = globals.apiHost;
const hasuractlApiPort = globals.apiPort;
// const hasuractlApiHost = globals.apiHost;
// const hasuractlApiPort = globals.apiPort;

const hasuractlUrl = `${hasuractlApiHost}:${hasuractlApiPort}`;
const hasuractlUrl = globals.migrateApiUrl;

const Endpoints = {
getSchema: `${baseUrl}/v1/query`,
Expand Down
8 changes: 4 additions & 4 deletions console/src/Globals.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ declare global {
interface Window {
__env: {
nodeEnv: string;
apiHost: string;
apiPort: string;
apiHost?: string;
apiPort?: string;
dataApiUrl: string;
urlPrefix: string;
adminSecret: string;
Expand All @@ -26,6 +26,7 @@ declare global {
serverVersion: string;
consolePath: string;
cliUUID: string;
migrateApiUrl: string;
};
sqlFormatter: unknown;
hljs: unknown;
Expand All @@ -48,8 +49,6 @@ if (
const isProduction = window.__env.nodeEnv !== 'development';

const globals = {
apiHost: window.__env.apiHost,
apiPort: window.__env.apiPort,
dataApiUrl: stripTrailingSlash(window.__env.dataApiUrl), // overridden below if server mode
urlPrefix: stripTrailingSlash(window.__env.urlPrefix || '/'), // overridden below if server mode in production
adminSecret: window.__env.adminSecret || null, // gets updated after login/logout in server mode
Expand All @@ -70,6 +69,7 @@ const globals = {
hasuraUUID: '',
telemetryNotificationShown: false,
isProduction,
migrateApiUrl: window.__env.migrateApiUrl,
};
if (globals.consoleMode === SERVER_CONSOLE_MODE) {
if (isProduction) {
Expand Down
Loading