Skip to content

Commit

Permalink
feat(templates): templating functions (#4635)
Browse files Browse the repository at this point in the history
This adds several functions which are available in most areas that use templates.
  • Loading branch information
james-d-elliott committed Dec 23, 2022
1 parent a916b65 commit 55a6794
Show file tree
Hide file tree
Showing 13 changed files with 673 additions and 187 deletions.
13 changes: 5 additions & 8 deletions cmd/authelia-gen/templates.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package main
import (
"embed"
"fmt"
"strings"
"text/template"

"github.com/authelia/authelia/v4/internal/templates"
Expand All @@ -24,13 +23,11 @@ var (
)

func newTMPL(name string) (tmpl *template.Template, err error) {
return template.New(name).
Funcs(template.FuncMap{
"stringsContains": strings.Contains,
"join": strings.Join,
"joinX": templates.StringJoinXFunc,
}).
Parse(mustLoadTmplFS(name))
funcs := templates.FuncMap()

funcs["joinX"] = templates.FuncStringJoinX

return template.New(name).Funcs(funcs).Parse(mustLoadTmplFS(name))
}

func mustLoadTmplFS(tmpl string) string {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ for, and the structure it must have.
│ │
│ └─⫸ Commit Scope: {{ joinX .Scopes.All "|" 70 "\n │ " }}
└─⫸ Commit Type: {{ join .Types.List "|" }}
└─⫸ Commit Type: {{ join "|" .Types.List }}
```

The `<type>` and `<summary>` fields are mandatory, the `(<scope>)` field is optional.
Expand All @@ -59,7 +59,7 @@ The `<type>` and `<summary>` fields are mandatory, the `(<scope>)` field is opti
{{ range .Types.Details }}
* __{{ .Name }}__ {{ .Description }}
{{- if .Scopes }}
(example scopes: {{ join .Scopes ", " }})
(example scopes: {{ join ", " .Scopes }})
{{- end }}
{{- end }}

Expand Down
2 changes: 1 addition & 1 deletion cmd/authelia-gen/templates/dot_commitlintrc.js.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ module.exports = {
"type-enum": [
2,
"always",
["{{ join .Types.List "\", \"" }}"],
["{{ join "\", \"" .Types.List }}"],
],
"scope-enum": [
2,
Expand Down
2 changes: 1 addition & 1 deletion cmd/authelia-gen/templates/web_i18n_index.ts.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ i18n.use(Backend)
default: ["{{ .Defaults.Language.Locale }}"],
{{- range .Languages }}
{{- if and (not (eq .Locale "en")) (not (eq (len .Fallbacks) 0)) }}
{{ if stringsContains .Locale "-" }}"{{ .Locale }}"{{ else }}{{ .Locale }}{{ end }}: [{{ range $i, $value := .Fallbacks }}{{ if eq $i 0 }}"{{ $value }}"{{ else }}, "{{ $value }}"{{ end }}{{ end }}],
{{ if contains "-" .Locale }}"{{ .Locale }}"{{ else }}{{ .Locale }}{{ end }}: [{{ range $i, $value := .Fallbacks }}{{ if eq $i 0 }}"{{ $value }}"{{ else }}, "{{ $value }}"{{ end }}{{ end }}],
{{- end }}
{{- end }}
},
Expand Down
119 changes: 2 additions & 117 deletions docs/content/en/configuration/methods/files.md
Original file line number Diff line number Diff line change
Expand Up @@ -187,121 +187,6 @@ output at each filter stage as a base64 string when trace logging is enabled.

#### Functions

In addition to the standard builtin functions we support several other functions.
In addition to the standard builtin functions we support several other functions which should operate similar.

##### iterate

The `iterate` function generates a list of numbers from 0 to the input provided. Useful for ranging over a list of
numbers.

Example:

```yaml
numbers:
{{- range $i := iterate 5 }}
- {{ $i }}
{{- end }}
```

##### env

The `env` function returns the value of an environment variable or a blank string.

Example:

```yaml
default_redirection_url: 'https://{{ env "DOMAIN" }}'
```

##### split

The `split` function splits a string by the separator.

Example:

```yaml
access_control:
rules:
- domain: 'app.{{ env "DOMAIN" }}'
policy: bypass
methods:
{{ range _, $method := split "GET,POST" "," }}
- {{ $method }}
{{ end }}
```

##### join

The `join` function is similar to [split](#split) but does the complete oppiste, joining an array of strings with a
separator.

Example:

```yaml
access_control:
rules:
- domain: ['app.{{ join (split (env "DOMAINS") ",") "', 'app." }}']
policy: bypass
```

##### contains

The `contains` function is a test function which checks if one string contains another string.

Example:

```yaml
{{ if contains (env "DOMAIN") "https://" }}
default_redirection_url: '{{ env "DOMAIN" }}'
{{ else }}
default_redirection_url: 'https://{{ env "DOMAIN" }}'
{{ end }}
```

##### hasPrefix

The `hasPrefix` function is a test function which checks if one string is prefixed with another string.

Example:

```yaml
{{ if hasPrefix (env "DOMAIN") "https://" }}
default_redirection_url: '{{ env "DOMAIN" }}'
{{ else }}
default_redirection_url: 'https://{{ env "DOMAIN" }}'
{{ end }}
```

##### hasSuffix

The `hasSuffix` function is a test function which checks if one string is suffixed with another string.

Example:

```yaml
{{ if hasSuffix (env "DOMAIN") "/" }}
default_redirection_url: 'https://{{ env "DOMAIN" }}'
{{ else }}
default_redirection_url: 'https://{{ env "DOMAIN" }}/'
{{ end }}
```

##### lower

The `lower` function is a conversion function which converts a string to all lowercase.

Example:

```yaml
default_redirection_url: 'https://{{ env "DOMAIN" | lower }}'
```

##### upper

The `upper` function is a conversion function which converts a string to all uppercase.

Example:

```yaml
default_redirection_url: 'https://{{ env "DOMAIN" | upper }}'
```
See the [Templating Reference Guide](../../reference/guides/templating.md) for more information.
5 changes: 5 additions & 0 deletions docs/content/en/reference/guides/notification-templates.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,11 @@ Some Additional examples for specific purposes can be found in the
The original template content can be found on
[GitHub](https://github.com/authelia/authelia/tree/master/internal/templates/src/notification).

## Functions

Several functions are implemented with the email templates. See the
[Templating Reference Guide](../../reference/guides/templating.md) for more information.

[host]: ../../configuration/notifications/smtp.md#host
[server_name]: ../../configuration/notifications/smtp.md#tls
[sender]: ../../configuration/notifications/smtp.md#sender
Expand Down
66 changes: 66 additions & 0 deletions docs/content/en/reference/guides/templating.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
---
title: "Templating"
description: "A reference guide on the templates system"
lead: "This section contains reference documentation for Authelia's templating capabilities."
date: 2022-12-23T18:31:05+11:00
draft: false
images: []
menu:
reference:
parent: "guides"
weight: 220
toc: true
---

Authelia has several methods where users can interact with templates.

## Functions

Functions can be used to perform specific actions when executing templates. The following is a simple guide on which
functions exist.

### Standard Functions

Go has a set of standard functions which can be used. See the [Go Documentation](https://pkg.go.dev/text/template#hdr-Functions)
for more information.

### Helm-like Functions

The following functions which mimic the behaviour of helm exist in most templating areas:

- env
- expandenv
- split
- splitList
- join
- contains
- hasPrefix
- hasSuffix
- lower
- upper
- title
- trim
- trimAll
- trimSuffix
- trimPrefix
- replace
- quote
- sha1sum
- sha256sum
- sha512sum
- squote
- now

See the [Helm Documentation](https://helm.sh/docs/chart_template_guide/function_list/) for more information. Please
note that only the functions listed above are supported.

__*Special Note:* The `env` and `expandenv` function automatically excludes environment variables that start with
`AUTHELIA_` or `X_AUTHELIA_` and end with one of `KEY`, `SECRET`, `PASSWORD`, `TOKEN`, or `CERTIFICATE_CHAIN`.__

### Special Functions

The following is a list of special functions and their syntax.

#### iterate

Input is a single uint. Returns a slice of uints from 0 to the provided uint.
3 changes: 3 additions & 0 deletions internal/configuration/const.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,7 @@ const (
errFmtDecodeHookCouldNotParseEmptyValue = "could not decode an empty value to a %s%s: %w"
)

// IMPORTANT: There is an uppercase copy of this in github.com/authelia/authelia/internal/templates named
// envSecretSuffixes.
// Make sure you update these at the same time.
var secretSuffixes = []string{"key", "secret", "password", "token", "certificate_chain"}
34 changes: 2 additions & 32 deletions internal/configuration/koanf_provider_filtered_file.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,32 +112,7 @@ func NewExpandEnvFileFilter() FileFilter {

// NewTemplateFileFilter is a FileFilter which passes the bytes through text/template.
func NewTemplateFileFilter() FileFilter {
data := &TemplateFileFilterData{
Env: map[string]string{},
}

for _, e := range os.Environ() {
kv := strings.SplitN(e, "=", 2)

if len(kv) != 2 {
continue
}

data.Env[kv[0]] = kv[1]
}

t := template.New("config.template").
Funcs(template.FuncMap{
"env": templates.StringMapLookupDefaultEmptyFunc(data.Env),
"split": templates.StringsSplitFunc,
"iterate": templates.IterateFunc,
"join": strings.Join,
"contains": strings.Contains,
"hasPrefix": strings.HasPrefix,
"hasSuffix": strings.HasSuffix,
"lower": strings.ToLower,
"upper": strings.ToUpper,
})
t := template.New("config.template").Funcs(templates.FuncMap())

log := logging.Logger()

Expand All @@ -148,7 +123,7 @@ func NewTemplateFileFilter() FileFilter {

buf := &bytes.Buffer{}

if err = t.Execute(buf, data); err != nil {
if err = t.Execute(buf, nil); err != nil {
return nil, err
}

Expand All @@ -163,8 +138,3 @@ func NewTemplateFileFilter() FileFilter {
return out, nil
}
}

// TemplateFileFilterData is the data available to the Go Template FileFilter.
type TemplateFileFilterData struct {
Env map[string]string
}

0 comments on commit 55a6794

Please sign in to comment.