🌱🏠 a cloud service to enable your own server (owned by you and running on your computer) to be accessible on the internet in seconds, no credit card required https://greenhouse.server.garden/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

105 lines
3.3 KiB

package main
import (
"crypto/sha256"
"encoding/json"
"fmt"
"log"
"net/http"
"strings"
)
func AddAPIRoutesToFrontend(app *FrontendApp) {
handleWithAPIToken(app, "/api/tenant_info", func(responseWriter http.ResponseWriter, request *http.Request, user Session) {
tenantInfo, err := app.Backend.GetTenantInfo(user.TenantId)
if err != nil {
app.unhandledError(responseWriter, err)
return
}
tenantInfoBytes, err := json.Marshal(tenantInfo)
if err != nil {
app.unhandledError(responseWriter, err)
return
}
responseWriter.Header().Set("Content-Type", "application/json")
responseWriter.Write(tenantInfoBytes)
})
handleWithAPIToken(app, "/api/client_config", func(responseWriter http.ResponseWriter, request *http.Request, user Session) {
if request.Method != "POST" {
responseWriter.Header().Add("Allow", "POST")
http.Error(responseWriter, "405 Method Not Allowed, try POST", http.StatusMethodNotAllowed)
return
}
newNodeId := request.URL.Query().Get("serverName")
if newNodeId == "" {
http.Error(responseWriter, "404 Not Found, a server name must be provided, like /api/client_config?serverName=my_server", http.StatusNotFound)
return
}
tenant, err := app.Model.GetTenant(user.TenantId)
if err != nil {
app.unhandledError(responseWriter, err)
return
}
clientConfig, err := app.Backend.ThresholdProvisioning.GetClientConfig(
user.TenantId, fmt.Sprintf("%s.%s", tenant.Subdomain, freeSubdomainDomain), newNodeId, user.APIToken,
)
if err != nil {
app.unhandledError(responseWriter, err)
return
}
clientConfigBytes, err := json.MarshalIndent(clientConfig, "", " ")
if err != nil {
app.unhandledError(responseWriter, err)
return
}
responseWriter.Header().Set("Content-Type", "application/json")
responseWriter.Write(clientConfigBytes)
})
}
func handleWithAPIToken(app *FrontendApp, path string, handler func(http.ResponseWriter, *http.Request, Session)) {
app.Router.HandleFunc(path, func(responseWriter http.ResponseWriter, request *http.Request) {
authorizationHeader := request.Header.Get("Authorization")
apiToken := strings.TrimPrefix(authorizationHeader, "Bearer ")
hasCorrectPrefix := !strings.HasPrefix(authorizationHeader, "Bearer ")
if hasCorrectPrefix || len(apiToken) < 10 {
log.Printf("authorizationHeader has invalid format: length=%d, hasCorrectPrefix=%t", len(apiToken), hasCorrectPrefix)
http.Error(responseWriter, "Unauthorized", http.StatusUnauthorized)
return
}
//log.Printf("<%s>\n", apiToken)
hashedAPIToken := sha256.Sum256([]byte(apiToken))
//log.Printf("h<%s>\n", fmt.Sprintf("%x", hashedAPIToken[:]))
user, err := app.Model.GetUserByAPIToken(fmt.Sprintf("%x", hashedAPIToken[:]))
if err != nil {
log.Printf("GetUserByAPIToken returned error: %+v", err)
http.Error(responseWriter, "Unauthorized", http.StatusUnauthorized)
return
}
if user == nil || user.TenantId == 0 || !user.EmailVerified {
http.Error(responseWriter, "Unauthorized", http.StatusUnauthorized)
return
}
user.APIToken = apiToken
handler(responseWriter, request, *user)
})
}
func splitUrlPath(path string) []string {
split := strings.Split(path, "/")
toReturn := []string{}
for _, s := range split {
if s != "" {
toReturn = append(toReturn, s)
}
}
return toReturn
}