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 }