Skip to content

Commit

Permalink
Tavern Fixes & Cleanup (#308)
Browse files Browse the repository at this point in the history
* Cleanup HTTP Handler Code

* Fix tavern/ent go generate

* fix http ui embedding

* cleanup metadata.yml parsing
  • Loading branch information
KCarretto authored Oct 5, 2023
1 parent d29a4a0 commit bf08fd1
Show file tree
Hide file tree
Showing 10 changed files with 92 additions and 123 deletions.
5 changes: 2 additions & 3 deletions tavern/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,19 +107,18 @@ func NewServer(ctx context.Context, options ...func(*Config)) (*Server, error) {
}

// Setup HTTP Handlers
httpLogger := log.New(os.Stderr, "[HTTP] ", log.Flags())
router := http.NewServeMux()
router.Handle("/status", newStatusHandler())
router.Handle("/oauth/login", auth.NewOAuthLoginHandler(cfg.oauth, privKey))
router.Handle("/oauth/authorize", auth.NewOAuthAuthorizationHandler(cfg.oauth, pubKey, client, "https://www.googleapis.com/oauth2/v3/userinfo"))
router.Handle("/graphql", newGraphQLHandler(client))
router.Handle("/cdn/", cdn.NewDownloadHandler(client))
router.Handle("/cdn/upload", cdn.NewUploadHandler(client))
fallbackhandler := www.FallbackAppHandler{}
router.Handle("/", auth.WithLoginRedirect("/oauth/login", &fallbackhandler))
router.Handle("/", auth.WithLoginRedirect("/oauth/login", www.NewHandler(httpLogger)))
router.Handle("/playground", auth.WithLoginRedirect("/oauth/login", playground.Handler("Tavern", "/graphql")))

// Log Middleware
httpLogger := log.New(os.Stderr, "[HTTP] ", log.Flags())
handlerWithLogging := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
authName := "unknown"
id := auth.IdentityFromContext(r.Context())
Expand Down
39 changes: 2 additions & 37 deletions tavern/internal/ent/generate.go
Original file line number Diff line number Diff line change
@@ -1,43 +1,8 @@
//go:build ignore
package ent

package main

import (
"log"

"entgo.io/contrib/entgql"
"entgo.io/ent/entc"
"entgo.io/ent/entc/gen"
)

//go:generate go run -mod=mod generate.go
//go:generate go run -mod=mod generate_code.go
//go:generate /bin/sh -c "cd ../graphql && go run -mod=mod github.com/99designs/gqlgen"
//go:generate /bin/sh -c "cat ../graphql/schema/* > ../graphql/schema.graphql"
//go:generate /bin/sh -c "cp ../graphql/schema.graphql ../www/schema.graphql"
//go:generate /bin/sh -c "cp ../graphql/schema.graphql ../../../implants/lib/tavern/graphql/schema.graphql"
//go:generate /bin/sh -c "cd ../../../implants/lib/tavern && ./codegen.sh"

func main() {
log.Println("generating entgo")
extensions, err := entgql.NewExtension(
entgql.WithSchemaGenerator(),
entgql.WithWhereInputs(true),
entgql.WithSchemaPath("../graphql/schema/ent.graphql"),
entgql.WithConfigPath("../graphql/gqlgen.yml"),
)
if err != nil {
log.Fatalf("creating entgql extension: %v", err)
}
opts := []entc.Option{
entc.Extensions(extensions),
entc.FeatureNames("privacy"),
}

if err := entc.Generate(
"./schema",
&gen.Config{},
opts...,
); err != nil {
log.Fatalf("running ent codegen: %v", err)
}
}
36 changes: 36 additions & 0 deletions tavern/internal/ent/generate_code.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
//go:build ignore

package main

import (
"log"

"entgo.io/contrib/entgql"
"entgo.io/ent/entc"
"entgo.io/ent/entc/gen"
)

func main() {
log.Println("generating entgo")
extensions, err := entgql.NewExtension(
entgql.WithSchemaGenerator(),
entgql.WithWhereInputs(true),
entgql.WithSchemaPath("../graphql/schema/ent.graphql"),
entgql.WithConfigPath("../graphql/gqlgen.yml"),
)
if err != nil {
log.Fatalf("creating entgql extension: %v", err)
}
opts := []entc.Option{
entc.Extensions(extensions),
entc.FeatureNames("privacy"),
}

if err := entc.Generate(
"./schema",
&gen.Config{},
opts...,
); err != nil {
log.Fatalf("running ent codegen: %v", err)
}
}
13 changes: 0 additions & 13 deletions tavern/internal/www/build/embed.go

This file was deleted.

13 changes: 0 additions & 13 deletions tavern/internal/www/embed-template.go.tmpl

This file was deleted.

68 changes: 36 additions & 32 deletions tavern/internal/www/http.go
Original file line number Diff line number Diff line change
@@ -1,45 +1,49 @@
package www

import (
"embed"
"fmt"
"log"
"net/http"
"strings"

"github.com/kcarretto/realm/tavern/internal/www/build"
)

// FallbackAppHandler is a custom handler for the single page react app - if the path doesn't exist the react app is returned.
type FallbackAppHandler struct{}
// Handler is a custom handler for the single page react app - if the path doesn't exist the react app is returned.
type Handler struct {
logger *log.Logger
}

func (h *FallbackAppHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// Extract the path from the http request
path := r.URL.Path[1:]
// Try to read the file requested
resp, err := build.Content.ReadFile(path)
if err != nil {
// If the file doesn't exist
if strings.Contains(err.Error(), "file does not exist") {
// Return our react apps main page and let it handle the route using react router.
resp, err := build.Content.ReadFile("index.html")
if err != nil {
println("Read error")
}
// Our index page will always be html
w.Header().Add("Content-Type", "text/html")
w.Write(resp)
} else {
println("Real error") // Should probably use the logging system.
}
} else {
// If the file does exist then it's a real embeded file and we'll write it's contents back.
// Since `w.Write` isn't aware of the file type we need to manually add the MIME types for files we'll serve.
// These MIME types only need to account for the files we'll be embedding through the `./build/` directory.
// Content embedded from the application's build directory, includes the latest build of the UI.
//
//go:embed build/*.png build/*.html build/*.json build/*.txt build/*.ico
//go:embed build/static/*
var Content embed.FS

// ServeHTTP provides the Tavern UI, if the requested file does not exist it will serve index.html
func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {

// Serve the requested file
path := fmt.Sprintf("build/%s", strings.TrimPrefix(r.URL.Path, "/"))
content, err := Content.ReadFile(path)
if err == nil {
if strings.HasSuffix(path, ".css") {
w.Header().Add("Content-Type", "text/css")
} else if strings.HasSuffix(path, ".js") {
w.Header().Add("Content-Type", "text/javascript")
} else if strings.HasSuffix(path, ".html") {
w.Header().Add("Content-Type", "text/html")
}
w.Write(resp)
w.Write(content)
return
}

// Otherwise serve index.html
index, err := Content.ReadFile("build/index.html")
if err != nil {
h.logger.Printf("fatal error: failed to read index.html: %v", err)
w.WriteHeader(http.StatusInternalServerError)
return
}
w.Write(index)
}

// NewHandler creates and returns a handler for the Tavern UI.
func NewHandler(logger *log.Logger) *Handler {
return &Handler{logger}
}
2 changes: 1 addition & 1 deletion tavern/internal/www/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build && cp ./embed-template.go.tmpl ./build/embed.go",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
Expand Down
6 changes: 3 additions & 3 deletions tavern/tomes/example/metadata.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name: example
description: An example tome!
paramdefs:
- name: msg
label: Message
- label: Message
name: msg
placeholder: Something to print
type: string
placeholder: Something to print
31 changes: 11 additions & 20 deletions tavern/tomes/parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,26 +12,17 @@ import (
"gopkg.in/yaml.v3"
)

type tomeParamDef struct {
Name string `yaml:"name" json:"name"`
Label string `yaml:"label" json:"label"`
Type string `yaml:"type" json:"type"`
Placeholder string `yaml:"placeholder" json:"placeholder"`
}

type tomeMetadata struct {
Name string
Description string
ParamDefs []interface{}
}

func convert_yaml_to_json(i interface{}) interface{} {
switch x := i.(type) {
case map[interface{}]interface{}:
m2 := map[string]interface{}{}
for k, v := range x {
m2[k.(string)] = convert_yaml_to_json(v)
}
return m2
case []interface{}:
for i, v := range x {
x[i] = convert_yaml_to_json(v)
}
}
return i
ParamDefs []tomeParamDef
}

// UploadTomes traverses the provided filesystem and creates tomes using the provided graph.
Expand Down Expand Up @@ -111,16 +102,16 @@ func UploadTomes(ctx context.Context, graph *ent.Client, fileSystem fs.ReadDirFS
return rollback(tx, fmt.Errorf("failed to parse and upload tome %q: %w", entry.Name(), err))
}

jsonified_paramdefs, err := json.Marshal(convert_yaml_to_json(metadata.ParamDefs))
paramdefs, err := json.Marshal(metadata.ParamDefs)
if err != nil {
return rollback(tx, fmt.Errorf("failed to prase param defs for %q: %w", metadata.Name, err))
return rollback(tx, fmt.Errorf("failed to parse param defs for %q: %w", metadata.Name, err))
}

// Create the tome
if _, err := graph.Tome.Create().
SetName(entry.Name()).
SetDescription(metadata.Description).
SetParamDefs(string(jsonified_paramdefs)).
SetParamDefs(string(paramdefs)).
SetEldritch(eldritch).
AddFiles(tomeFiles...).
Save(ctx); err != nil {
Expand Down
2 changes: 1 addition & 1 deletion tavern/tomes/parse_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ func TestUploadTomes(t *testing.T) {
require.NotNil(t, testTome)
assert.Equal(t, `print(input_params['msg'])`, testTome.Eldritch)
assert.Equal(t, `An example tome!`, testTome.Description)
assert.Equal(t, `[{"label":"Message","name":"msg","placeholder":"Something to print","type":"string"}]`, testTome.ParamDefs)
assert.Equal(t, `[{"name":"msg","label":"Message","type":"string","placeholder":"Something to print"}]`, testTome.ParamDefs)
testTomeFiles, err := testTome.Files(ctx)
assert.NoError(t, err)
assert.Len(t, testTomeFiles, 1)
Expand Down

0 comments on commit bf08fd1

Please sign in to comment.