Skip to content

Commit

Permalink
Merge pull request #101 from carverauto/99-portal-api
Browse files Browse the repository at this point in the history
99 portal api
  • Loading branch information
mfreeman451 authored Apr 26, 2024
2 parents ac28394 + ddb349c commit 7cfc21b
Show file tree
Hide file tree
Showing 15 changed files with 1,196 additions and 78 deletions.
46 changes: 46 additions & 0 deletions cmd/api/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package main

import (
"context"
"github.com/carverauto/threadr/pkg/api/firebase"
"github.com/carverauto/threadr/pkg/api/routes"
"github.com/gofiber/fiber/v2"
"github.com/joho/godotenv"
"log"
"time"
)

func main() {
err := godotenv.Load()
if err != nil {
log.Println("Error loading .env file")
}

app := fiber.New(
fiber.Config{
EnablePrintRoutes: true,
},
)

ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()

FirebaseApp, err := firebase.SetupFirebaseApp(ctx)
if err != nil {
log.Println("Error initializing Firebase App:", err)
return
}

// Group for routes that require tenant and role verification
secure := app.Group("/secure")
routes.SetupSecureRoutes(secure, FirebaseApp)

// General and admin routes setup
routes.SetupRoutes(app, FirebaseApp)

fErr := app.Listen(":3001")
if fErr != nil {
log.Println("Error starting the server:", fErr)
return
}
}
91 changes: 91 additions & 0 deletions cmd/client/admin/claims.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package main

import (
"bytes"
"encoding/json"
"fmt"
"log"
"net/http"
)

// GetClaims gets custom claims for a user
func GetClaims(apiURL, apiKey, userID string) error {
url := fmt.Sprintf(apiURL, userID)
log.Println("URL:", url)

req, err := http.NewRequest("GET", url, nil)
if err != nil {
return err
}

log.Printf("API Key: %s\n", apiKey)

req.Header.Set("Content-Type", "application/json")
req.Header.Set("X-API-Key", apiKey)

client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()

// print the body
buf := new(bytes.Buffer)
_, err = buf.ReadFrom(resp.Body)
if err != nil {
return err
}
body := buf.String()
fmt.Println(body)

if resp.StatusCode != http.StatusOK {
return fmt.Errorf("failed to get claims, server responded with status code: %d", resp.StatusCode)
}

fmt.Println("Custom claims retrieved successfully.")
return nil
}

// SendClaimsUpdate sends a POST request to set custom claims for a user
func SendClaimsUpdate(apiURL, apiKey, userID string, userClaims map[string]string) error {
claims := Claims{
UserID: userID,
Claims: userClaims,
}

claimsJSON, err := json.Marshal(claims)
if err != nil {
return err
}

req, err := http.NewRequest("POST", apiURL, bytes.NewBuffer(claimsJSON))
if err != nil {
return err
}

req.Header.Set("Content-Type", "application/json")
req.Header.Set("X-API-Key", apiKey)

client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()

// print the body
buf := new(bytes.Buffer)
_, err = buf.ReadFrom(resp.Body)
if err != nil {
return err
}
body := buf.String()
fmt.Println(body)

if resp.StatusCode != http.StatusOK {
return fmt.Errorf("failed to set claims, server responded with status code: %d", resp.StatusCode)
}

return nil
}
24 changes: 24 additions & 0 deletions cmd/client/admin/firebase.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package main

import (
"context"
firebase "firebase.google.com/go"
"fmt"
threadrFirebase "github.com/carverauto/threadr/pkg/api/firebase"
"log"
"time"
)

// firebaseAuth is a function that logs in a user
func firebaseAuth() (*firebase.App, error) {
fmt.Println("Logging in user...")
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()

FirebaseApp, err := threadrFirebase.SetupFirebaseApp(ctx)
if err != nil {
log.Println("Error initializing Firebase App:", err)
return nil, err
}
return FirebaseApp, nil
}
53 changes: 53 additions & 0 deletions cmd/client/admin/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package main

import (
"fmt"
"log"
"os"
)

type Claims struct {
UserID string `json:"userId"`
Claims map[string]string `json:"claims"`
}

const (
setClaimsURL = "http://localhost:3001/admin/set-claims"
getClaimsURL = "http://localhost:3001/admin/get-claims/%s"
secureEndpoint = "http://localhost:3001/secure/%s"
)

func main() {
apiKey := os.Getenv("ADMIN_API_KEY")
if apiKey == "" {
fmt.Println("ADMIN_API_KEY is not set.")
return
}

// Define the user and claims you want to set
userID := os.Getenv("FIREBASE_USER_ID")
userClaims := map[string]string{
"role": "admin",
"tenantId": "threadr",
}

err := SendClaimsUpdate(setClaimsURL, apiKey, userID, userClaims)
if err != nil {
fmt.Println("Error setting custom claims:", err)
return
}

log.Printf("Getting custom claims for user: %s\n", userID)

err = GetClaims(getClaimsURL, apiKey, userID)
if err != nil {
fmt.Println("Error getting custom claims:", err)
return
}

// Test the secure endpoint that requires tenant ID in the URL
log.Printf("Accessing secure tenant endpoint for tenant: %s\n", userClaims["tenantId"])
if err := AccessSecureEndpoint(fmt.Sprintf(secureEndpoint, userClaims["tenantId"]), apiKey); err != nil {
fmt.Println("Error accessing secure endpoint:", err)
}
}
43 changes: 43 additions & 0 deletions cmd/client/admin/secure.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package main

import (
"bytes"
"fmt"
"log"
"net/http"
)

// AccessSecureEndpoint accesses a secure endpoint that requires tenant-level security
func AccessSecureEndpoint(url, apiKey string) error {
log.Println("URL:", url)

req, err := http.NewRequest("GET", url, nil)
if err != nil {
return err
}

req.Header.Set("Authorization", "Bearer <Token>") // This should be your Firebase token
req.Header.Set("X-API-Key", apiKey)

client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()

buf := new(bytes.Buffer)
_, err = buf.ReadFrom(resp.Body)
if err != nil {
return err
}
body := buf.String()
fmt.Println(body)

if resp.StatusCode != http.StatusOK {
return fmt.Errorf("failed to access secure endpoint, server responded with status code: %d", resp.StatusCode)
}

fmt.Println("Secure endpoint accessed successfully.")
return nil
}
63 changes: 63 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
module github.com/carverauto/threadr

go 1.21.3

require (
firebase.google.com/go v3.13.0+incompatible
firebase.google.com/go/v4 v4.14.0
github.com/gofiber/fiber/v2 v2.52.4
github.com/joho/godotenv v1.5.1
github.com/sacsand/gofiber-firebaseauth v1.4.3
google.golang.org/api v0.176.0
)

require (
cloud.google.com/go v0.112.1 // indirect
cloud.google.com/go/auth v0.2.2 // indirect
cloud.google.com/go/auth/oauth2adapt v0.2.1 // indirect
cloud.google.com/go/compute/metadata v0.3.0 // indirect
cloud.google.com/go/firestore v1.15.0 // indirect
cloud.google.com/go/iam v1.1.7 // indirect
cloud.google.com/go/longrunning v0.5.5 // indirect
cloud.google.com/go/storage v1.40.0 // indirect
github.com/MicahParks/keyfunc v1.9.0 // indirect
github.com/andybalholm/brotli v1.0.5 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/go-logr/logr v1.4.1 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/google/s2a-go v0.1.7 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect
github.com/googleapis/gax-go/v2 v2.12.3 // indirect
github.com/klauspost/compress v1.17.0 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-runewidth v0.0.15 // indirect
github.com/rivo/uniseg v0.2.0 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasthttp v1.51.0 // indirect
github.com/valyala/tcplisten v1.0.0 // indirect
go.opencensus.io v0.24.0 // indirect
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect
go.opentelemetry.io/otel v1.24.0 // indirect
go.opentelemetry.io/otel/metric v1.24.0 // indirect
go.opentelemetry.io/otel/trace v1.24.0 // indirect
golang.org/x/crypto v0.22.0 // indirect
golang.org/x/net v0.24.0 // indirect
golang.org/x/oauth2 v0.19.0 // indirect
golang.org/x/sync v0.6.0 // indirect
golang.org/x/sys v0.19.0 // indirect
golang.org/x/text v0.14.0 // indirect
golang.org/x/time v0.5.0 // indirect
google.golang.org/appengine v1.6.8 // indirect
google.golang.org/appengine/v2 v2.0.2 // indirect
google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20240314234333-6e1732d8331c // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240415180920-8c6c420018be // indirect
google.golang.org/grpc v1.63.2 // indirect
google.golang.org/protobuf v1.33.0 // indirect
)
Loading

0 comments on commit 7cfc21b

Please sign in to comment.