Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Embed UI & Login Redirects #280

Merged
merged 4 commits into from
Sep 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ cmd/implants/Cargo.lock

# Build artifacts
dist/**
build/**

# Binaries for programs and plugins
*.exe
Expand Down
73 changes: 38 additions & 35 deletions tavern/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,18 @@ import (
"net/http"
"os"

"entgo.io/contrib/entgql"
"github.com/kcarretto/realm/tavern/graphql"
"github.com/kcarretto/realm/tavern/tomes"

"entgo.io/contrib/entgql"
gqlgraphql "github.com/99designs/gqlgen/graphql"
"github.com/99designs/gqlgen/graphql/handler"
"github.com/99designs/gqlgen/graphql/playground"
"github.com/kcarretto/realm/tavern/auth"
"github.com/kcarretto/realm/tavern/ent"
"github.com/kcarretto/realm/tavern/ent/migrate"
"github.com/kcarretto/realm/tavern/graphql"
"github.com/kcarretto/realm/tavern/internal/cdn"
"github.com/kcarretto/realm/tavern/internal/www"
"github.com/urfave/cli"
)

Expand Down Expand Up @@ -105,45 +106,16 @@ func NewServer(ctx context.Context, options ...func(*Config)) (*Server, error) {
createTestData(ctx, client)
}

// Create GraphQL Handler
srv := handler.NewDefaultServer(graphql.NewSchema(client))
srv.Use(entgql.Transactioner{TxOpener: client})

// GraphQL Logging
gqlLogger := log.New(os.Stderr, "[GraphQL] ", log.Flags())
srv.AroundOperations(func(ctx context.Context, next gqlgraphql.OperationHandler) gqlgraphql.ResponseHandler {
oc := gqlgraphql.GetOperationContext(ctx)
reqVars, err := json.Marshal(oc.Variables)
if err != nil {
gqlLogger.Printf("[ERROR] failed to marshal variables to JSON: %v", err)
return next(ctx)
}

authName := "unknown"
id := auth.IdentityFromContext(ctx)
if id != nil {
authName = id.String()
}

gqlLogger.Printf("%s (%s): %s", oc.OperationName, authName, string(reqVars))
return next(ctx)
})

// Setup HTTP Handler
// Setup HTTP Handlers
router := http.NewServeMux()
router.Handle("/status", newStatusHandler())
router.Handle("/",
playground.Handler("Tavern", "/graphql"),
)
router.Handle("/graphql", http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Access-Control-Allow-Headers", "*")
srv.ServeHTTP(w, req)
}))
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))
KCarretto marked this conversation as resolved.
Show resolved Hide resolved
router.Handle("/cdn/", cdn.NewDownloadHandler(client))
router.Handle("/cdn/upload", cdn.NewUploadHandler(client))
router.Handle("/", auth.WithLoginRedirect("/oauth/login", www.NewAppHandler()))
router.Handle("/playground", auth.WithLoginRedirect("/oauth/login", playground.Handler("Tavern", "/graphql")))

// Log Middleware
httpLogger := log.New(os.Stderr, "[HTTP] ", log.Flags())
Expand Down Expand Up @@ -181,3 +153,34 @@ func NewServer(ctx context.Context, options ...func(*Config)) (*Server, error) {
client: client,
}, nil
}

func newGraphQLHandler(client *ent.Client) http.Handler {
srv := handler.NewDefaultServer(graphql.NewSchema(client))
srv.Use(entgql.Transactioner{TxOpener: client})

// GraphQL Logging
gqlLogger := log.New(os.Stderr, "[GraphQL] ", log.Flags())
srv.AroundOperations(func(ctx context.Context, next gqlgraphql.OperationHandler) gqlgraphql.ResponseHandler {
oc := gqlgraphql.GetOperationContext(ctx)
reqVars, err := json.Marshal(oc.Variables)
if err != nil {
gqlLogger.Printf("[ERROR] failed to marshal variables to JSON: %v", err)
return next(ctx)
}

authName := "unknown"
id := auth.IdentityFromContext(ctx)
if id != nil {
authName = id.String()
}

gqlLogger.Printf("%s (%s): %s", oc.OperationName, authName, string(reqVars))
return next(ctx)
})

return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Access-Control-Allow-Headers", "*")
srv.ServeHTTP(w, req)
})
}
12 changes: 12 additions & 0 deletions tavern/auth/middleware.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,3 +82,15 @@ func Middleware(handler http.Handler, graph *ent.Client) http.HandlerFunc {
handler.ServeHTTP(w, r)
})
}

// WithLoginRedirect will redirect requests for the provided handler to the provided redirect URL if the request is unauthenticated.
func WithLoginRedirect(redirect string, handler http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
if !IsAuthenticatedContext(req.Context()) {
http.Redirect(w, req, redirect, http.StatusFound)
return
}
handler.ServeHTTP(w, req)
})

}
4 changes: 4 additions & 0 deletions tavern/internal/www/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,7 @@ _If this is your first time contributing WWW changes in this dev environment, re
2. Run `go run ./tavern` to start the teamserver (for the GraphQL API) run in the project root
* Note: to run the teamserver with test data (useful for UI development), run `ENABLE_TEST_DATA=1 go run ./tavern` instead
3. In a separate terminal, navigate to the [UI Root /cmd/tavern/internal/www](https://github.com/KCarretto/realm/tree/main/cmd/tavern/internal/www) and run `npm start`

## Building the Application

When you're ready to include changes to the UI in the tavern binary, you'll need to run `npm build` to update files in the `build/` directory. These files will automatically be bundled into new compliations of the tavern binary.
16 changes: 16 additions & 0 deletions tavern/internal/www/build/asset-manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"files": {
"main.css": "/static/css/main.ed062423.css",
"main.js": "/static/js/main.1ffa92c8.js",
"static/js/787.4af0fb89.chunk.js": "/static/js/787.4af0fb89.chunk.js",
"static/media/eldrich.png": "/static/media/eldrich.a80c74e8249d2461e174.png",
"index.html": "/index.html",
"main.ed062423.css.map": "/static/css/main.ed062423.css.map",
"main.1ffa92c8.js.map": "/static/js/main.1ffa92c8.js.map",
"787.4af0fb89.chunk.js.map": "/static/js/787.4af0fb89.chunk.js.map"
},
"entrypoints": [
"static/css/main.ed062423.css",
"static/js/main.1ffa92c8.js"
]
}
9 changes: 9 additions & 0 deletions tavern/internal/www/build/embed.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package build

import "embed"

// Content embedded from the application's build directory, includes the latest build of the UI.
//
//go:embed *.png *.html *.json *.txt *.ico
//go:embed static/*
var Content embed.FS
Binary file added tavern/internal/www/build/favicon.ico
Binary file not shown.
1 change: 1 addition & 0 deletions tavern/internal/www/build/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><meta name="description" content="Web site created using create-react-app"/><link rel="apple-touch-icon" href="/logo192.png"/><link rel="manifest" href="/manifest.json"/><title>React App</title><script defer="defer" src="/static/js/main.1ffa92c8.js"></script><link href="/static/css/main.ed062423.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>
3 changes: 3 additions & 0 deletions tavern/internal/www/build/logo192.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions tavern/internal/www/build/logo512.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
25 changes: 25 additions & 0 deletions tavern/internal/www/build/manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"short_name": "React App",
"name": "Create React App Sample",
"icons": [
{
"src": "favicon.ico",
"sizes": "64x64 32x32 24x24 16x16",
"type": "image/x-icon"
},
{
"src": "logo192.png",
"type": "image/png",
"sizes": "192x192"
},
{
"src": "logo512.png",
"type": "image/png",
"sizes": "512x512"
}
],
"start_url": ".",
"display": "standalone",
"theme_color": "#000000",
"background_color": "#ffffff"
}
3 changes: 3 additions & 0 deletions tavern/internal/www/build/robots.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# https://www.robotstxt.org/robotstxt.html
User-agent: *
Disallow:
4 changes: 4 additions & 0 deletions tavern/internal/www/build/static/css/main.ed062423.css

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions tavern/internal/www/build/static/css/main.ed062423.css.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading