wisski-cloud-distillery/internal/dis/component/resolver/resolver.go
2023-11-02 12:05:13 +01:00

130 lines
3.4 KiB
Go

package resolver
import (
"context"
"fmt"
"net/http"
"regexp"
"time"
"github.com/FAU-CDI/wdresolve"
"github.com/FAU-CDI/wdresolve/resolvers"
"github.com/FAU-CDI/wisski-distillery/internal/dis/component"
"github.com/FAU-CDI/wisski-distillery/internal/dis/component/auth"
"github.com/FAU-CDI/wisski-distillery/internal/dis/component/auth/scopes"
"github.com/FAU-CDI/wisski-distillery/internal/dis/component/instances"
"github.com/FAU-CDI/wisski-distillery/internal/dis/component/server/assets"
"github.com/FAU-CDI/wisski-distillery/internal/dis/component/server/templating"
"github.com/rs/zerolog"
"github.com/tkw1536/pkglib/httpx"
"github.com/tkw1536/pkglib/lazy"
_ "embed"
)
type Resolver struct {
component.Base
dependencies struct {
Instances *instances.Instances
Templating *templating.Templating
Auth *auth.Auth
}
prefixes lazy.Lazy[map[string]string] // cached prefixes (from the server)
RefreshInterval time.Duration
}
var (
_ component.Routeable = (*Resolver)(nil)
_ component.Cronable = (*Resolver)(nil)
)
func (resolver *Resolver) Routes() component.Routes {
return component.Routes{
Prefix: "/wisski/get/",
Aliases: []string{"/go/"},
CSRF: false,
MenuTitle: "Resolver",
MenuPriority: component.MenuResolver,
}
}
//go:embed "resolver.html"
var resolverHTML []byte
var resolverTemplate = templating.Parse[resolverContext](
"resolver.html", resolverHTML, nil,
templating.Title("Resolver"),
templating.Assets(assets.AssetsDefault),
)
type resolverContext struct {
templating.RuntimeFlags
wdresolve.IndexContext
}
var (
menuResolver = component.MenuItem{Title: "Resolver", Path: "/wisski/get/"}
)
func (resolver *Resolver) HandleRoute(ctx context.Context, route string) (http.Handler, error) {
// get the resolver template
tpl := resolverTemplate.Prepare(
resolver.dependencies.Templating,
templating.Crumbs(
menuResolver,
),
)
t := tpl.Template()
// extract a logger and the fallback
logger := zerolog.Ctx(ctx)
fallback := &resolvers.Regexp{
Data: map[string]string{},
}
// handle the default domain name!
domainName := resolver.Config.HTTP.PrimaryDomain
if domainName != "" {
fallback.Data[fmt.Sprintf("^https?://(.*)\\.%s", regexp.QuoteMeta(domainName))] = fmt.Sprintf("https://$1.%s", domainName)
logger.Info().Str("name", domainName).Msg("registering default domain")
}
// handle the extra domains!
for _, domain := range resolver.Config.HTTP.ExtraDomains {
fallback.Data[fmt.Sprintf("^https?://(.*)\\.%s", regexp.QuoteMeta(domain))] = fmt.Sprintf("https://$1.%s", domainName)
logger.Info().Str("name", domainName).Msg("registering legacy domain")
}
p := wdresolve.ResolveHandler{
HandleIndex: func(context wdresolve.IndexContext, w http.ResponseWriter, r *http.Request) {
ctx := resolverContext{
IndexContext: context,
}
if resolver.dependencies.Auth.CheckScope("", scopes.ScopeUserValid, r) != nil {
ctx.IndexContext.Prefixes = nil
}
httpx.WriteHTML(tpl.Context(r, ctx), nil, t, "", w, r)
},
Resolver: resolvers.InOrder{
resolver,
fallback,
},
TrustXForwardedProto: true,
}
return p, nil
}
func (resolver *Resolver) Target(uri string) string {
return wdresolve.PrefixTarget(resolver, uri)
}
// Prefixes returns a cached list of prefixes
func (resolver *Resolver) Prefixes() (prefixes map[string]string) {
return resolver.prefixes.Get(nil) // by precondition there always is a cached value
}