Skip to content

Commit

Permalink
feature: embed profile ui files
Browse files Browse the repository at this point in the history
  • Loading branch information
greenpau committed Mar 26, 2024
1 parent d5e997a commit 92f0dbe
Show file tree
Hide file tree
Showing 25 changed files with 1,889 additions and 22 deletions.
59 changes: 59 additions & 0 deletions assets/scripts/update_ui_apps.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#!/bin/bash
set -e

printf "Updating UI apps\n"

SCRIPT_DIR=$(cd -P -- "$(dirname -- "$0")" && printf '%s\n' "$(pwd -P)")
ASSETS_DIR=$(dirname -- "$SCRIPT_DIR")
ROOT_DIR=$(dirname -- "$ASSETS_DIR")

echo $SCRIPT_DIR
echo $ROOT_DIR


UI_FILE=pkg/authn/ui/apps.go

declare -a _APPS
_APPS[${#_APPS[@]}]="profile"

cat << 'EOF' > ${UI_FILE}
package ui
import (
"embed"
)
var (
//go:embed profile
embedFileSystem embed.FS
embedPages = map[string]string{
EOF

for APP_ID in "${!_APPS[@]}"; do
cd $ROOT_DIR
APP_NAME=${_APPS[$APP_ID]};
echo "Updating ${APP_NAME} app";
APP_DIR=../../authcrunch/authcrunch-ui/frontend/${APP_NAME}/build
if [ -d ${APP_DIR} ]; then
echo "App directory ${APP_DIR} exists."
else
echo "ERROR: App directory ${APP_DIR} does not exist."
exit 1
fi
rm -rf pkg/authn/ui/${APP_NAME}
cp -R ../../authcrunch/authcrunch-ui/frontend/${APP_NAME}/build pkg/authn/ui/${APP_NAME}
echo "\"${APP_NAME}/\": \"${APP_NAME}/index.html\"," >> ${UI_FILE}

cd pkg/authn/ui
for APP_UI_FILE in `find ${APP_NAME} -type f`; do
echo "\"${APP_UI_FILE}\": \"${APP_UI_FILE}\"," >> apps.go
done
cd $ROOT_DIR
done


cat << 'EOF' >> ${UI_FILE}
}
)
EOF
go fmt ${UI_FILE}
77 changes: 77 additions & 0 deletions pkg/authn/handle_http_apps.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// Copyright 2022 Paul Greenberg [email protected]
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package authn

import (
"context"
"fmt"
"io"
"net/http"
"strings"

"github.com/greenpau/go-authcrunch/pkg/authn/enums/role"
"github.com/greenpau/go-authcrunch/pkg/authn/ui"
"github.com/greenpau/go-authcrunch/pkg/requests"
"github.com/greenpau/go-authcrunch/pkg/user"
)

func (p *Portal) handleHTTPApps(ctx context.Context, w http.ResponseWriter, r *http.Request, rr *requests.Request, usr *user.User, appName string) error {
p.disableClientCache(w)
p.injectRedirectURL(ctx, w, r, rr)
if usr == nil {
return p.handleHTTPError(ctx, w, r, rr, http.StatusUnauthorized)
}

if err := p.authorizedRole(usr, []role.Kind{role.Admin, role.User}, rr.Response.Authenticated); err != nil {
return p.handleHTTPError(ctx, w, r, rr, http.StatusForbidden)
}

var assetPath string
switch {
case appName == "profile":
assetPath = strings.TrimPrefix(r.URL.Path, rr.Upstream.BasePath)
if !strings.HasPrefix(assetPath, "profile/") {
assetPath = appName + "/" + assetPath
}
default:
return p.handleHTTPRenderError(ctx, w, r, rr, fmt.Errorf("file not found"))
}

p.logRequest(appName+" app assets", r, rr)
asset, err := ui.AppAssets.GetAsset(assetPath)
if err != nil {
if strings.HasSuffix(assetPath, "/") || strings.Count(assetPath, "/") >= 3 || strings.HasSuffix(assetPath, "/new") {
asset, err = ui.AppAssets.GetAsset(appName + "/")
if err != nil {
return p.handleHTTPError(ctx, w, r, rr, http.StatusNotFound)
}
} else {
return p.handleHTTPError(ctx, w, r, rr, http.StatusNotFound)
}
}

w.Header().Set("Content-Type", asset.ContentType)
w.Header().Set("Etag", asset.Checksum)
w.Header().Set("Cache-Control", "max-age=7200")
if match := r.Header.Get("If-None-Match"); match != "" {
if strings.Contains(match, asset.Checksum) {
w.WriteHeader(http.StatusNotModified)
return nil
}
}
w.WriteHeader(http.StatusOK)
io.WriteString(w, asset.Content)
return nil
}
41 changes: 21 additions & 20 deletions pkg/authn/respond_http.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ func (p *Portal) handleHTTP(ctx context.Context, w http.ResponseWriter, r *http.
case r.URL.Path == "/" || r.URL.Path == "/auth" || r.URL.Path == "/auth/":
p.injectRedirectURL(ctx, w, r, rr)
return p.handleHTTPRedirect(ctx, w, r, rr, "/login")
case strings.Contains(r.URL.Path, "/profile/"):
return p.handleHTTPApps(ctx, w, r, rr, usr, "profile")
case strings.Contains(r.URL.Path, "/assets/") || strings.Contains(r.URL.Path, "/favicon"):
return p.handleHTTPStaticAssets(ctx, w, r, rr)
case strings.Contains(r.URL.Path, "/portal"):
Expand Down Expand Up @@ -132,26 +134,26 @@ func (p *Portal) handleHTTPError(ctx context.Context, w http.ResponseWriter, r *
return p.handleHTTPRenderHTML(ctx, w, code, content.Bytes())
}

func (p *Portal) handleHTTPGeneric(ctx context.Context, w http.ResponseWriter, r *http.Request, rr *requests.Request, code int, msg string) error {
p.disableClientCache(w)
resp := p.ui.GetArgs()
resp.BaseURL(rr.Upstream.BasePath)
resp.PageTitle = msg
switch code {
case http.StatusServiceUnavailable:
resp.Data["message"] = "This service is not available to you."
}
// func (p *Portal) handleHTTPGeneric(ctx context.Context, w http.ResponseWriter, r *http.Request, rr *requests.Request, code int, msg string) error {
// p.disableClientCache(w)
// resp := p.ui.GetArgs()
// resp.BaseURL(rr.Upstream.BasePath)
// resp.PageTitle = msg
// switch code {
// case http.StatusServiceUnavailable:
// resp.Data["message"] = "This service is not available to you."
// }

resp.Data["authenticated"] = rr.Response.Authenticated
resp.Data["go_back_url"] = rr.Upstream.BasePath
content, err := p.ui.Render("generic", resp)
if err != nil {
return p.handleHTTPRenderError(ctx, w, r, rr, err)
}
return p.handleHTTPRenderHTML(ctx, w, code, content.Bytes())
}
// resp.Data["authenticated"] = rr.Response.Authenticated
// resp.Data["go_back_url"] = rr.Upstream.BasePath
// content, err := p.ui.Render("generic", resp)
// if err != nil {
// return p.handleHTTPRenderError(ctx, w, r, rr, err)
// }
// return p.handleHTTPRenderHTML(ctx, w, code, content.Bytes())
// }

func (p *Portal) handleHTTPRedirect(ctx context.Context, w http.ResponseWriter, r *http.Request, rr *requests.Request, location string) error {
func (p *Portal) handleHTTPRedirect(_ context.Context, w http.ResponseWriter, _ *http.Request, rr *requests.Request, location string) error {
p.disableClientCache(w)
location = rr.Upstream.BaseURL + path.Join(rr.Upstream.BasePath, location)
w.Header().Set("Location", location)
Expand All @@ -166,7 +168,7 @@ func (p *Portal) handleHTTPRedirect(ctx context.Context, w http.ResponseWriter,
return nil
}

func (p *Portal) handleHTTPRedirectSeeOther(ctx context.Context, w http.ResponseWriter, r *http.Request, rr *requests.Request, location string) error {
func (p *Portal) handleHTTPRedirectSeeOther(_ context.Context, w http.ResponseWriter, _ *http.Request, rr *requests.Request, location string) error {
p.disableClientCache(w)
location = rr.Upstream.BaseURL + path.Join(rr.Upstream.BasePath, location)
w.Header().Set("Location", location)
Expand Down Expand Up @@ -253,7 +255,6 @@ func (p *Portal) injectSessionID(ctx context.Context, w http.ResponseWriter, r *
}
rr.Upstream.SessionID = util.GetRandomStringFromRange(36, 46)
w.Header().Add("Set-Cookie", p.cookie.GetSessionCookie(addrutil.GetSourceHost(r), rr.Upstream.SessionID))
return
}

func (p *Portal) injectRedirectURL(ctx context.Context, w http.ResponseWriter, r *http.Request, rr *requests.Request) {
Expand Down
46 changes: 46 additions & 0 deletions pkg/authn/ui/apps.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// Copyright 2022 Paul Greenberg [email protected]
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package ui

import (
"embed"
)

var (
//go:embed profile
embedFileSystem embed.FS
embedPages = map[string]string{
"profile/": "profile/index.html",
"profile/fonts/Inter-Black.ttf": "profile/fonts/Inter-Black.ttf",
"profile/fonts/Inter-Bold.ttf": "profile/fonts/Inter-Bold.ttf",
"profile/fonts/Inter-ExtraBold.ttf": "profile/fonts/Inter-ExtraBold.ttf",
"profile/fonts/Inter-ExtraLight.ttf": "profile/fonts/Inter-ExtraLight.ttf",
"profile/fonts/Inter-Light.ttf": "profile/fonts/Inter-Light.ttf",
"profile/fonts/Inter-Medium.ttf": "profile/fonts/Inter-Medium.ttf",
"profile/fonts/Inter-Regular.ttf": "profile/fonts/Inter-Regular.ttf",
"profile/fonts/Inter-SemiBold.ttf": "profile/fonts/Inter-SemiBold.ttf",
"profile/fonts/Inter-Thin.ttf": "profile/fonts/Inter-Thin.ttf",
"profile/fonts/fonts.css": "profile/fonts/fonts.css",
"profile/images/banner.jpg": "profile/images/banner.jpg",
"profile/assets/index-DLdtk2Ib.css": "profile/assets/index-DLdtk2Ib.css",
"profile/assets/index-DOtSzC14.js": "profile/assets/index-DOtSzC14.js",
"profile/favicon.ico": "profile/favicon.ico",
"profile/logo192.png": "profile/logo192.png",
"profile/logo512.png": "profile/logo512.png",
"profile/manifest.json": "profile/manifest.json",
"profile/robots.txt": "profile/robots.txt",
"profile/index.html": "profile/index.html",
}
)
1 change: 1 addition & 0 deletions pkg/authn/ui/profile/assets/index-DLdtk2Ib.css

Large diffs are not rendered by default.

Loading

0 comments on commit 92f0dbe

Please sign in to comment.