Add ability to connect with settings from third-party backend
This commit is contained in:
@@ -2,13 +2,17 @@ package api
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
neturl "net/url"
|
neturl "net/url"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/tuvistavie/securerandom"
|
||||||
|
|
||||||
"github.com/sosedoff/pgweb/pkg/bookmarks"
|
"github.com/sosedoff/pgweb/pkg/bookmarks"
|
||||||
"github.com/sosedoff/pgweb/pkg/client"
|
"github.com/sosedoff/pgweb/pkg/client"
|
||||||
@@ -69,6 +73,59 @@ func GetSessions(c *gin.Context) {
|
|||||||
c.JSON(200, map[string]int{"sessions": len(DbSessions)})
|
c.JSON(200, map[string]int{"sessions": len(DbSessions)})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ConnectWithBackend(c *gin.Context) {
|
||||||
|
resp, err := http.PostForm(command.Opts.ConnectBackend, neturl.Values{
|
||||||
|
"resource": {c.Param("resource")},
|
||||||
|
"token": {command.Opts.ConnectToken},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
c.JSON(400, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
data, err := ioutil.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
c.JSON(400, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
sessionId, err := securerandom.Uuid()
|
||||||
|
if err != nil {
|
||||||
|
c.JSON(400, Error{err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.Request.Header.Add("x-session-id", sessionId)
|
||||||
|
|
||||||
|
config := struct {
|
||||||
|
DatabaseUrl string `json:"database_url"`
|
||||||
|
}{}
|
||||||
|
|
||||||
|
if err := json.Unmarshal(data, &config); err != nil {
|
||||||
|
c.JSON(400, Error{err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
cl, err := client.NewFromUrl(config.DatabaseUrl, nil)
|
||||||
|
if err != nil {
|
||||||
|
c.JSON(400, Error{err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
cl.External = true
|
||||||
|
|
||||||
|
_, err = cl.Info()
|
||||||
|
if err == nil {
|
||||||
|
err = setClient(c, cl)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
cl.Close()
|
||||||
|
c.JSON(400, Error{err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Redirect(301, fmt.Sprintf("/%s?session=%s", command.Opts.Prefix, sessionId))
|
||||||
|
}
|
||||||
|
|
||||||
func Connect(c *gin.Context) {
|
func Connect(c *gin.Context) {
|
||||||
if command.Opts.LockSession {
|
if command.Opts.LockSession {
|
||||||
c.JSON(400, Error{"Session is locked"})
|
c.JSON(400, Error{"Session is locked"})
|
||||||
@@ -141,6 +198,12 @@ func SwitchDb(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Do not allow switching databases for connections from third-party backends
|
||||||
|
if conn.External {
|
||||||
|
c.JSON(400, Error{"Session is locked"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
currentUrl, err := neturl.Parse(conn.ConnectionString)
|
currentUrl, err := neturl.Parse(conn.ConnectionString)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(400, Error{"Unable to parse current connection string"})
|
c.JSON(400, Error{"Unable to parse current connection string"})
|
||||||
@@ -199,6 +262,12 @@ func Disconnect(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func GetDatabases(c *gin.Context) {
|
func GetDatabases(c *gin.Context) {
|
||||||
|
conn := DB(c)
|
||||||
|
if conn.External {
|
||||||
|
c.JSON(403, Error{"Not permitted"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
names, err := DB(c).Databases()
|
names, err := DB(c).Databases()
|
||||||
serveResult(names, err, c)
|
serveResult(names, err, c)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,4 +49,6 @@ func SetupRoutes(router *gin.Engine) {
|
|||||||
api.GET("/bookmarks", GetBookmarks)
|
api.GET("/bookmarks", GetBookmarks)
|
||||||
api.GET("/export", DataExport)
|
api.GET("/export", DataExport)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
group.GET("/connect/:resource", ConnectWithBackend)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ type Client struct {
|
|||||||
tunnel *Tunnel
|
tunnel *Tunnel
|
||||||
serverVersion string
|
serverVersion string
|
||||||
lastQueryTime time.Time
|
lastQueryTime time.Time
|
||||||
|
External bool
|
||||||
History []history.Record `json:"history"`
|
History []history.Record `json:"history"`
|
||||||
ConnectionString string `json:"connection_string"`
|
ConnectionString string `json:"connection_string"`
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package command
|
package command
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@@ -29,6 +30,8 @@ type Options struct {
|
|||||||
Bookmark string `short:"b" long:"bookmark" description:"Bookmark to use for connection. Bookmark files are stored under $HOME/.pgweb/bookmarks/*.toml" default:""`
|
Bookmark string `short:"b" long:"bookmark" description:"Bookmark to use for connection. Bookmark files are stored under $HOME/.pgweb/bookmarks/*.toml" default:""`
|
||||||
BookmarksDir string `long:"bookmarks-dir" description:"Overrides default directory for bookmark files to search" default:""`
|
BookmarksDir string `long:"bookmarks-dir" description:"Overrides default directory for bookmark files to search" default:""`
|
||||||
DisablePrettyJson bool `long:"no-pretty-json" description:"Disable JSON formatting feature for result export" default:"false"`
|
DisablePrettyJson bool `long:"no-pretty-json" description:"Disable JSON formatting feature for result export" default:"false"`
|
||||||
|
ConnectBackend string `long:"connect-backend"`
|
||||||
|
ConnectToken string `long:"connect-token"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var Opts Options
|
var Opts Options
|
||||||
@@ -64,5 +67,14 @@ func ParseOptions() error {
|
|||||||
Opts.AuthPass = os.Getenv("AUTH_PASS")
|
Opts.AuthPass = os.Getenv("AUTH_PASS")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if Opts.ConnectBackend != "" {
|
||||||
|
if !Opts.Sessions {
|
||||||
|
return errors.New("--sessions flag must be set")
|
||||||
|
}
|
||||||
|
if Opts.ConnectToken == "" {
|
||||||
|
return errors.New("--connect-token flag must be set")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -1204,6 +1204,15 @@ $(document).ready(function() {
|
|||||||
initEditor();
|
initEditor();
|
||||||
addShortcutTooltips();
|
addShortcutTooltips();
|
||||||
|
|
||||||
|
// Set session from the url
|
||||||
|
var reqUrl = new URL(window.location);
|
||||||
|
var sessionId = reqUrl.searchParams.get("session");
|
||||||
|
|
||||||
|
if (sessionId && sessionId != "") {
|
||||||
|
sessionStorage.setItem("session_id", sessionId);
|
||||||
|
window.history.pushState({}, document.title, window.location.pathname);
|
||||||
|
}
|
||||||
|
|
||||||
apiCall("get", "/connection", {}, function(resp) {
|
apiCall("get", "/connection", {}, function(resp) {
|
||||||
if (resp.error) {
|
if (resp.error) {
|
||||||
connected = false;
|
connected = false;
|
||||||
|
|||||||
Reference in New Issue
Block a user