package main
import (
"crypto/sha256"
"encoding/json"
"fmt"
"log"
"net/http"
"regexp"
"strings"
)
func AddAPIRoutesToFrontend ( app * FrontendApp ) {
handleWithAPIToken ( app , "/api/tenant_info" , func ( responseWriter http . ResponseWriter , request * http . Request , user Session ) {
//log.Println("GET /api/tenant_info")
tenantInfo , err := app . Backend . GetTenantInfo ( user . TenantId )
if err != nil {
app . unhandledError ( responseWriter , request , err )
return
}
tenantInfoBytes , err := json . Marshal ( tenantInfo )
if err != nil {
app . unhandledError ( responseWriter , request , 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 := strings . ToLower ( 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
}
subdomainRegex := regexp . MustCompile ( "^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?$" )
if ! subdomainRegex . MatchString ( newNodeId ) {
http . Error ( responseWriter , "400 Bad Request, the server name must be a valid subdomain. It should only contain letters, numbers, and dashes" , http . StatusBadRequest )
return
}
// used to use fmt.Sprintf("%s.%s", tenant.Subdomain, freeSubdomainDomain) as the greenhouseDomain
// tenant, err := app.Model.GetTenant(user.TenantId)
// if err != nil {
// app.unhandledError(responseWriter, request, err)
// return
// }
clientConfig , err := app . Backend . ThresholdProvisioning . GetClientConfig (
user . TenantId , greenhouseExternalDomain , newNodeId , user . APIToken ,
)
if err != nil {
app . unhandledError ( responseWriter , request , err )
return
}
clientConfigBytes , err := json . MarshalIndent ( clientConfig , "" , " " )
if err != nil {
app . unhandledError ( responseWriter , request , 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
}