Skip to content

Commit 9f35815

Browse files
feat: add backend support for workspace env vars (GET/PUT endpoints, proxy to 3rd party (#2763)
* feat: add backend support for workspace env vars (GET/PUT endpoints, proxy to 3rd party) * feat: get the pool api per request --------- Co-authored-by: kevkevinpal <oapallikunnel@gmail.com>
1 parent 8765a53 commit 9f35815

3 files changed

Lines changed: 167 additions & 0 deletions

File tree

config/config.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ var V2BotToken string
4848
var IsV2Payment bool = false
4949
var FfWebsocket bool = false
5050
var SWAuth string
51+
var POOLManagerAPIUsername string
52+
var POOLManagerAPIPassword string
5153

5254
func InitConfig() {
5355
Host = os.Getenv("LN_SERVER_BASE_URL")
@@ -71,6 +73,8 @@ func InitConfig() {
7173
FfWebsocket = os.Getenv("FF_WEBSOCKET") == "true"
7274
LogLevel = strings.ToUpper(os.Getenv("LOG_LEVEL"))
7375
SWAuth = os.Getenv("SWAUTH")
76+
POOLManagerAPIUsername = os.Getenv("POOL_MANAGER_API_USERNAME")
77+
POOLManagerAPIPassword = os.Getenv("POOL_MANAGER_API_PASSWORD")
7478

7579
// Add to super admins
7680
SuperAdmins = StripSuperAdmins(AdminStrings)

handlers/workspaces.go

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,12 @@ import (
1010
"regexp"
1111
"strings"
1212
"time"
13+
"bytes"
1314

1415
"github.com/go-chi/chi"
1516
"github.com/rs/xid"
1617
"github.com/stakwork/sphinx-tribes/auth"
18+
"github.com/stakwork/sphinx-tribes/config"
1719
"github.com/stakwork/sphinx-tribes/db"
1820
"github.com/stakwork/sphinx-tribes/logger"
1921
"github.com/stakwork/sphinx-tribes/utils"
@@ -1751,3 +1753,162 @@ func (oh *workspaceHandler) RefreshCodeGraph(w http.ResponseWriter, r *http.Requ
17511753
w.WriteHeader(http.StatusOK)
17521754
w.Write(body)
17531755
}
1756+
1757+
func GetPoolManagerApiKey() (string, error) {
1758+
type AuthBody struct {
1759+
Username string `json:"username"`
1760+
Password string `json:"password"`
1761+
}
1762+
1763+
type Response struct {
1764+
Success bool `json:"success"`
1765+
Token string `json:"token"`
1766+
}
1767+
1768+
url := "https://workspaces.sphinx.chat/api/auth/login"
1769+
1770+
// Create request body
1771+
body := AuthBody{
1772+
Username: config.POOLManagerAPIUsername,
1773+
Password: config.POOLManagerAPIPassword,
1774+
}
1775+
1776+
// Marshal body to JSON
1777+
jsonBody, err := json.Marshal(body)
1778+
if err != nil {
1779+
return "", fmt.Errorf("failed to marshal request body: %w", err)
1780+
}
1781+
1782+
// Create HTTP request
1783+
req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonBody))
1784+
if err != nil {
1785+
return "", fmt.Errorf("failed to create request: %w", err)
1786+
}
1787+
1788+
// Set content type for JSON
1789+
req.Header.Set("Content-Type", "application/json")
1790+
// Note: Removed Authorization header as it seems unnecessary for login
1791+
// req.Header.Set("Authorization", "Bearer "+config.POOLManagerAPIKey)
1792+
1793+
// Make HTTP request
1794+
resp, err := http.DefaultClient.Do(req)
1795+
if err != nil {
1796+
return "", fmt.Errorf("failed to contact 3rd party service: %w", err)
1797+
}
1798+
defer resp.Body.Close()
1799+
1800+
// Check status code
1801+
if resp.StatusCode != http.StatusOK {
1802+
return "", fmt.Errorf("unexpected status code: %d", resp.StatusCode)
1803+
}
1804+
1805+
// Read and parse response
1806+
var response Response
1807+
if err := json.NewDecoder(resp.Body).Decode(&response); err != nil {
1808+
return "", fmt.Errorf("failed to decode response: %w", err)
1809+
}
1810+
1811+
// Check if request was successful
1812+
if !response.Success {
1813+
return "", fmt.Errorf("authentication failed")
1814+
}
1815+
1816+
return response.Token, nil
1817+
}
1818+
1819+
// GetWorkspaceEnvVars proxies env var fetch to 3rd party
1820+
func (oh *workspaceHandler) GetWorkspaceEnvVars(w http.ResponseWriter, r *http.Request) {
1821+
workspaceUUID := chi.URLParam(r, "workspace_uuid")
1822+
codespaces, err := oh.db.GetCodeSpaceMapByWorkspace(workspaceUUID)
1823+
if err != nil || len(codespaces) == 0 || codespaces[0].CodeSpaceURL == "" {
1824+
w.WriteHeader(http.StatusNotFound)
1825+
json.NewEncoder(w).Encode(map[string]string{"error": "codespaceURL not found for workspace"})
1826+
return
1827+
}
1828+
codespaceURL := codespaces[0].CodeSpaceURL
1829+
url := "https://workspaces.sphinx.chat/api/pools/" + codespaceURL
1830+
1831+
req, err := http.NewRequest("GET", url, nil)
1832+
if err != nil {
1833+
w.WriteHeader(http.StatusInternalServerError)
1834+
json.NewEncoder(w).Encode(map[string]string{"error": "failed to create request"})
1835+
return
1836+
}
1837+
POOLManagerAPIKey, err := GetPoolManagerApiKey()
1838+
if err != nil {
1839+
w.WriteHeader(http.StatusInternalServerError)
1840+
json.NewEncoder(w).Encode(map[string]string{"error": "failed to contact 3rd party service"})
1841+
return
1842+
}
1843+
req.Header.Set("Authorization", "Bearer "+POOLManagerAPIKey)
1844+
resp, err := http.DefaultClient.Do(req)
1845+
if err != nil {
1846+
w.WriteHeader(http.StatusBadGateway)
1847+
json.NewEncoder(w).Encode(map[string]string{"error": "failed to contact 3rd party service"})
1848+
return
1849+
}
1850+
defer resp.Body.Close()
1851+
if resp.StatusCode != 200 {
1852+
w.WriteHeader(resp.StatusCode)
1853+
io.Copy(w, resp.Body)
1854+
return
1855+
}
1856+
var result struct {
1857+
Config struct {
1858+
EnvVars []map[string]interface{} `json:"env_vars"`
1859+
} `json:"config"`
1860+
}
1861+
if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
1862+
w.WriteHeader(http.StatusInternalServerError)
1863+
json.NewEncoder(w).Encode(map[string]string{"error": "failed to decode response"})
1864+
return
1865+
}
1866+
w.WriteHeader(http.StatusOK)
1867+
json.NewEncoder(w).Encode(result.Config.EnvVars)
1868+
}
1869+
1870+
// UpdateWorkspaceEnvVars proxies env var update to 3rd party
1871+
func (oh *workspaceHandler) UpdateWorkspaceEnvVars(w http.ResponseWriter, r *http.Request) {
1872+
workspaceUUID := chi.URLParam(r, "workspace_uuid")
1873+
codespaces, err := oh.db.GetCodeSpaceMapByWorkspace(workspaceUUID)
1874+
if err != nil || len(codespaces) == 0 || codespaces[0].CodeSpaceURL == "" {
1875+
w.WriteHeader(http.StatusNotFound)
1876+
json.NewEncoder(w).Encode(map[string]string{"error": "codespaceURL not found for workspace"})
1877+
return
1878+
}
1879+
codespaceURL := codespaces[0].CodeSpaceURL
1880+
url := "https://workspaces.sphinx.chat/api/pools/" + codespaceURL
1881+
1882+
var body struct {
1883+
EnvVars []map[string]string `json:"env_vars"`
1884+
}
1885+
if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
1886+
w.WriteHeader(http.StatusBadRequest)
1887+
json.NewEncoder(w).Encode(map[string]string{"error": "invalid request body"})
1888+
return
1889+
}
1890+
b, _ := json.Marshal(map[string]interface{}{"env_vars": body.EnvVars})
1891+
req, err := http.NewRequest("PUT", url, strings.NewReader(string(b)))
1892+
if err != nil {
1893+
w.WriteHeader(http.StatusInternalServerError)
1894+
json.NewEncoder(w).Encode(map[string]string{"error": "failed to create request"})
1895+
return
1896+
}
1897+
POOLManagerAPIKey, err := GetPoolManagerApiKey()
1898+
if err != nil {
1899+
w.WriteHeader(http.StatusInternalServerError)
1900+
json.NewEncoder(w).Encode(map[string]string{"error": "failed to contact 3rd party service"})
1901+
return
1902+
}
1903+
req.Header.Set("Authorization", "Bearer "+POOLManagerAPIKey)
1904+
req.Header.Set("Content-Type", "application/json")
1905+
resp, err := http.DefaultClient.Do(req)
1906+
if err != nil {
1907+
w.WriteHeader(http.StatusBadGateway)
1908+
json.NewEncoder(w).Encode(map[string]string{"error": "failed to contact 3rd party service"})
1909+
return
1910+
}
1911+
defer resp.Body.Close()
1912+
w.WriteHeader(resp.StatusCode)
1913+
io.Copy(w, resp.Body)
1914+
}

routes/workspaces.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ func WorkspaceRoutes() chi.Router {
5656
r.Post("/codegraph/refresh/{workspace_uuid}", workspaceHandlers.RefreshCodeGraph)
5757

5858
r.Get("/{workspace_uuid}/lastwithdrawal", workspaceHandlers.GetLastWithdrawal)
59+
r.Get("/{workspace_uuid}/env_vars", workspaceHandlers.GetWorkspaceEnvVars)
60+
r.Put("/{workspace_uuid}/env_vars", workspaceHandlers.UpdateWorkspaceEnvVars)
5961

6062
r.Post("/codegraph", workspaceHandlers.CreateOrEditWorkspaceCodeGraph)
6163
r.Get("/codegraph/{uuid}", workspaceHandlers.GetWorkspaceCodeGraphByUUID)

0 commit comments

Comments
 (0)