@@ -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+ }
0 commit comments