package relations import ( "context" "net/url" "regexp" "strings" "text/template" "github.com/opencloud-eu/opencloud/pkg/oidc" "github.com/opencloud-eu/opencloud/services/webfinger/pkg/config" "github.com/opencloud-eu/opencloud/services/webfinger/pkg/service/v0" "github.com/opencloud-eu/opencloud/services/webfinger/pkg/webfinger" ) const ( OpenCloudInstanceRel = "http://webfinger.opencloud/rel/server-instance" ) type compiledInstance struct { config.Instance compiledRegex *regexp.Regexp hrefTemplate *template.Template } type openCloudInstance struct { instances []compiledInstance openCloudURL string instanceHost string } // OpenCloudInstance adds one or more OpenCloud instance relations func OpenCloudInstance(instances []config.Instance, openCloudURL string) (service.RelationProvider, error) { compiledInstances := make([]compiledInstance, 0, len(instances)) var err error for _, instance := range instances { compiled := compiledInstance{Instance: instance} compiled.compiledRegex, err = regexp.Compile(instance.Regex) if err != nil { return nil, err } compiled.hrefTemplate, err = template.New(instance.Claim + ":" + instance.Regex + ":" + instance.Href).Parse(instance.Href) if err != nil { return nil, err } compiledInstances = append(compiledInstances, compiled) } u, err := url.Parse(openCloudURL) if err != nil { return nil, err } return &openCloudInstance{ instances: compiledInstances, openCloudURL: openCloudURL, instanceHost: u.Host + u.Path, }, nil } func (l *openCloudInstance) Add(ctx context.Context, jrd *webfinger.JSONResourceDescriptor) { if jrd == nil { jrd = &webfinger.JSONResourceDescriptor{} } if claims := oidc.FromContext(ctx); claims != nil { if value, ok := claims[oidc.PreferredUsername].(string); ok { jrd.Subject = "acct:" + value + "@" + l.instanceHost } else if value, ok := claims[oidc.Email].(string); ok { jrd.Subject = "mailto:" + value } // allow referencing OC_URL in the template claims["OC_URL"] = l.openCloudURL for _, instance := range l.instances { if value, ok := claims[instance.Claim].(string); ok && instance.compiledRegex.MatchString(value) { var tmplWriter strings.Builder instance.hrefTemplate.Execute(&tmplWriter, claims) jrd.Links = append(jrd.Links, webfinger.Link{ Rel: OpenCloudInstanceRel, Href: tmplWriter.String(), Titles: instance.Titles, }) if instance.Break { break } } } } }