Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
a9858a9
hint new feat in readme
CodeShellDev Sep 17, 2025
f4cde7b
remove `ls`
CodeShellDev Sep 17, 2025
76d4fc7
Merge pull request #48 from CodeShellDev/main
CodeShellDev Sep 17, 2025
6dab8c1
Merge branch 'feat/message-templates' of https://github.com/codeshell…
CodeShellDev Sep 19, 2025
0f63ec8
remove aliases
CodeShellDev Sep 19, 2025
cb2673f
testing
CodeShellDev Sep 19, 2025
3846eba
improved json templating
CodeShellDev Sep 19, 2025
f7fb698
added aliases middleware
CodeShellDev Sep 19, 2025
c2e5b51
temporarily updated defaults
CodeShellDev Sep 19, 2025
8f4bf51
added message templates
CodeShellDev Sep 19, 2025
e5f104e
updated template middleware
CodeShellDev Sep 19, 2025
805a19f
renamed messageAlias to alias
CodeShellDev Sep 19, 2025
57db640
updated json templating
CodeShellDev Sep 19, 2025
290db8f
possible fix by updating regex
CodeShellDev Sep 19, 2025
6bbf7f1
debugging issue with `{{@key}}` not working
CodeShellDev Sep 19, 2025
bb4efc2
added missing message templating
CodeShellDev Sep 19, 2025
dd711ab
debugging issue
CodeShellDev Sep 19, 2025
96e6525
testing
CodeShellDev Sep 19, 2025
fa6e5e4
debugging
CodeShellDev Sep 19, 2025
2fb052e
debugging incoming data
CodeShellDev Sep 19, 2025
aad457a
debugging incoming body
CodeShellDev Sep 19, 2025
a08813f
extensive debugging
CodeShellDev Sep 19, 2025
0464a52
narrowing down root of issue
CodeShellDev Sep 19, 2025
8dd1f92
actually assigned bodyData to the Body 🤦
CodeShellDev Sep 19, 2025
1778e97
on the hunt for a new issue, @var expanding to full json body
CodeShellDev Sep 19, 2025
577a30d
fixed body getting tostring'ed and put into `message`
CodeShellDev Sep 19, 2025
c068d38
process json templating in one combined render
CodeShellDev Sep 19, 2025
afd9ba5
set modifiedBody flag
CodeShellDev Sep 19, 2025
f7dd059
fixed aliases processing
CodeShellDev Sep 19, 2025
c34d67c
debug
CodeShellDev Sep 19, 2025
3693c91
fixed misintepretation of data alias logic
CodeShellDev Sep 19, 2025
f38215b
moved modifiedBody flag
CodeShellDev Sep 19, 2025
d668f2b
add
CodeShellDev Sep 19, 2025
edd2f96
debugging missing aliases
CodeShellDev Sep 19, 2025
5b112f7
updated defaults
CodeShellDev Sep 19, 2025
d72320e
finished testing
CodeShellDev Sep 19, 2025
c6f400b
reworked readme for dataAliases
CodeShellDev Sep 19, 2025
e9e74bf
Update config.yml
CodeShellDev Sep 19, 2025
7118d06
Update README.template.md
CodeShellDev Sep 19, 2025
f9ac0d1
Update defaults.yml
CodeShellDev Sep 19, 2025
3c09f73
Update config.yml
CodeShellDev Sep 19, 2025
1a4ae0e
Update README.template.md
CodeShellDev Sep 19, 2025
6e95497
Update README.template.md
CodeShellDev Sep 20, 2025
18fa18f
Update README.template.md
CodeShellDev Sep 20, 2025
26e1a7e
Merge branch 'main' into feat/message-templates
CodeShellDev Sep 20, 2025
98f9ad6
Merge branch 'main' into feat/message-templates
CodeShellDev Sep 20, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 45 additions & 31 deletions .github/templates/README.template.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,12 @@ endpoint restrictions, placeholders, flexible configuration
- [Getting Started](#getting-started)
- [Setup](#setup)
- [Usage](#usage)
- [Best Practices](#security-best-practices)
- [Best Practices](#best-practices)
- [Configuration](#configuration)
- [Endpoints](#endpoints)
- [Variables](#variables)
- [Data Aliases](#data-aliases)
- [Message Templates](#message-templates)
- [Contributing](#contributing)
- [Support](#support)
- [License](#license)
Expand Down Expand Up @@ -119,31 +121,24 @@ curl -X POST -H "Content-Type: application/json" -H "Authorization: Bearer API_T

#### Placeholders

If you are not comfortable / don't want to hardcode your Number for example and/or Recipients in you, may use **Placeholders** in your Request. See [Custom Variables](#variables).
If you are not comfortable / don't want to hardcode your Number for example and/or Recipients in you, may use **Placeholders** in your Request.

These Placeholders can be used in the Request Query or the Body of a Request like so:
You can use [**Variable**](#variables) `{{.NUMBER}}` Placeholders and **Body** Placeholders `{{@data.key}}`.

**Body**
| Type | Example |
| :---- | :--------------------------------------------------------------- |
| Body | `{"number": "{{ .NUMBER }}", "recipients": "{{ .RECIPIENTS }}"}` |
| Query | `http://sec-signal-api:8880/v1/receive/?@number={{.NUMBER}}` |
| Path | `http://sec-signal-api:8880/v1/receive/{{.NUMBER}}` |

You can also combine them:

```json
{
"number": "{{ .NUMBER }}",
"recipients": "{{ .RECIPIENTS }}"
"content": "{{.NUMBER}} -> {{.RECIPIENTS}}"
}
```

**Query**

```
http://sec-signal-api:8880/v1/receive/?@number={{.NUMBER}}
```

**Path**

```
http://sec-signal-api:8880/v1/receive/{{.NUMBER}}
```

#### KeyValue Pair Injection

In some cases you may not be able to access / modify the Request Body, in that case specify needed values in the Request Query:
Expand All @@ -153,7 +148,7 @@ In some cases you may not be able to access / modify the Request Body, in that c
In order to differentiate Injection Queries and _regular_ Queries
you have to add `@` in front of any KeyValue Pair assignment.

Supported types include **strings**, **ints** and **arrays**. See [Formatting](#string-to-type).
Supported types include **strings**, **ints**, **arrays** and **json dictionaries**. See [Formatting](#string-to-type).

## Best Practices

Expand Down Expand Up @@ -293,12 +288,27 @@ settings:
recipients: ["+123400002", "group.id", "user.id"]
```

### Message Aliases
### Message Templates

To improve compatibility with other services Secured Signal API provides **Message Aliases** for the `message` attribute.
To customize the `message` attribute you can use **Message Templates** to build your message by using other Body Keys and Variables.
Use `messageTemplate` to configure:

```yaml
settings:
messageTemplate: |
Your Message:
{{@message}}.
Sent with Secured Signal API.
```

Use `{{@data.key}}` to reference Body Keys and `{{.KEY}}` for Variables.

### Data Aliases

To improve compatibility with other services Secured Signal API provides **Data Aliases** and a built-in `message` Alias.

<details>
<summary><strong>Default Message Aliases</strong></summary>
<summary><strong>Default `message` Aliases</strong></summary>

| Alias | Score | Alias | Score |
| ------------ | ----- | ---------------- | ----- |
Expand All @@ -312,23 +322,27 @@ To improve compatibility with other services Secured Signal API provides **Messa

</details>

Secured Signal API will pick the best scoring Message Alias (if available) to extract the correct message from the Request Body.
Secured Signal API will pick the best scoring Data Alias (if available) to extract set the Key to the correct Value from the Request Body.

Message Aliases can be added by setting `messageAliases` in your config:
Data Aliases can be added by setting `dataAliases` in your config:

```yaml
settings:
messageAliases:
[
{ alias: "msg", score: 80 },
{ alias: "data.message", score: 79 },
{ alias: "array[0].message", score: 78 },
]
dataAliases:
"@message":
[
{ alias: "msg", score: 80 },
{ alias: "data.message", score: 79 },
{ alias: "array[0].message", score: 78 },
]
".NUMBER": [{ alias: "phone_number", score: 100 }]
```

Use `@` for aliasing Body Keys and `.` for aliasing Variables.

### Port

To change the Port which Secured Signal API uses, you need to set `server.port` in your config. (default: `8880`)
To change the Port which Secured Signal API uses, you need to set `service.port` in your config. (default: `8880`)

### Log Level

Expand Down
44 changes: 5 additions & 39 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ endpoint restrictions, placeholders, flexible configuration
- [Configuration](#configuration)
- [Endpoints](#endpoints)
- [Variables](#variables)
- [Message Templates](#message-templates)
- [Contributing](#contributing)
- [Support](#support)
- [License](#license)
Expand Down Expand Up @@ -65,10 +66,9 @@ services:
container_name: secured-signal
environment:
API__URL: http://signal-api:8080
SETTINGS__VARIABLES__RECIPIENTS:
'[+123400002, +123400003, +123400004]'
SETTINGS__VARIABLES__RECIPIENTS: "[+123400002, +123400003, +123400004]"
SETTINGS__VARIABLES__NUMBER: "+123400001"
API__TOKENS: '[LOOOOOONG_STRING]'
API__TOKENS: "[LOOOOOONG_STRING]"
ports:
- "8880:8880"
restart: unless-stopped
Expand Down Expand Up @@ -100,10 +100,9 @@ services:
container_name: secured-signal
environment:
API__URL: http://signal-api:8080
SETTINGS__VARIABLES__RECIPIENTS:
'[+123400002,+123400003,+123400004]'
SETTINGS__VARIABLES__RECIPIENTS: "[+123400002,+123400003,+123400004]"
SETTINGS__VARIABLES__NUMBER: "+123400001"
API__TOKENS: '[LOOOOOONG_STRING]'
API__TOKENS: "[LOOOOOONG_STRING]"
labels:
- traefik.enable=true
- traefik.http.routers.signal-api.rule=Host(`signal-api.mydomain.com`)
Expand Down Expand Up @@ -438,39 +437,6 @@ settings:
recipients: ["+123400002", "group.id", "user.id"]
```

### Message Aliases

To improve compatibility with other services Secured Signal API provides **Message Aliases** for the `message` attribute.

<details>
<summary><strong>Default Message Aliases</strong></summary>

| Alias | Score | Alias | Score |
| ------------ | ----- | ---------------- | ----- |
| msg | 100 | data.content | 9 |
| content | 99 | data.description | 8 |
| description | 98 | data.text | 7 |
| text | 20 | data.summary | 6 |
| summary | 15 | data.details | 5 |
| details | 14 | body | 2 |
| data.message | 10 | data | 1 |

</details>

Secured Signal API will pick the best scoring Message Alias (if available) to extract the correct message from the Request Body.

Message Aliases can be added by setting `messageAliases` in your config:

```yaml
settings:
messageAliases:
[
{ alias: "msg", score: 80 },
{ alias: "data.message", score: 79 },
{ alias: "array[0].message", score: 78 },
]
```

### Port

To change the Port which Secured Signal API uses, you need to set `server.port` in your config. (default: `8880`)
Expand Down
35 changes: 18 additions & 17 deletions data/defaults.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,26 @@ service:
logLevel: info

settings:
messageAliases:
[
{ alias: msg, score: 100 },
{ alias: content, score: 99 },
{ alias: description, score: 98 },
{ alias: text, score: 20 },
{ alias: summary, score: 15 },
{ alias: details, score: 14 },
dataAliases:
"@message":
[
{ alias: msg, score: 100 },
{ alias: content, score: 99 },
{ alias: description, score: 98 },
{ alias: text, score: 20 },
{ alias: summary, score: 15 },
{ alias: details, score: 14 },

{ alias: data.message, score: 10 },
{ alias: data.content, score: 9 },
{ alias: data.description, score: 8 },
{ alias: data.text, score: 7 },
{ alias: data.summary, score: 6 },
{ alias: data.details, score: 5 },
{ alias: data.message, score: 10 },
{ alias: data.content, score: 9 },
{ alias: data.description, score: 8 },
{ alias: data.text, score: 7 },
{ alias: data.summary, score: 6 },
{ alias: data.details, score: 5 },

{ alias: body, score: 2 },
{ alias: data, score: 1 },
]
{ alias: body, score: 2 },
{ alias: data, score: 1 },
]

variables:
recipients: ${RECIPIENTS}
Expand Down
14 changes: 11 additions & 3 deletions examples/config.yml
Original file line number Diff line number Diff line change
@@ -1,18 +1,26 @@
# Example Config (all configurations shown)
service:
port: 8880

api:
port: 8880
url: http://signal-api:8080
tokens: [token1, token2]

logLevel: INFO
logLevel: info

settings:
messageTemplate: |
You've got a Notification:
{{@message}}
At {{@data.timestamp}} on {{@data.date}}.
Send using {{.NUMBER}}.

variables:
number: "+123400001"
recipients: ["+123400002", "group.id", "user.id"]

messageAliases: [{ alias: "msg", score: 100 }]
dataAliases:
"@message": [{ alias: "msg", score: 100 }]

blockedEndpoints:
- /v1/about
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,24 @@ import (
request "github.com/codeshelldev/secured-signal-api/utils/request"
)

type BodyMiddleware struct {
type AliasMiddleware struct {
Next http.Handler
}

func (data BodyMiddleware) Use() http.Handler {
func (data AliasMiddleware) Use() http.Handler {
next := data.Next

return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
messageAliases := getSettingsByReq(req).MESSAGE_ALIASES
settings := getSettingsByReq(req)

if messageAliases == nil {
messageAliases = getSettings("*").MESSAGE_ALIASES
dataAliases := settings.DATA_ALIASES

if dataAliases == nil {
dataAliases = getSettings("*").DATA_ALIASES
}

if settings.VARIABLES == nil {
settings.VARIABLES = getSettings("*").VARIABLES
}

body, err := request.GetReqBody(w, req)
Expand All @@ -38,13 +44,20 @@ func (data BodyMiddleware) Use() http.Handler {
if !body.Empty {
bodyData = body.Data

content, ok := bodyData["message"]
aliasData := processDataAliases(dataAliases, bodyData)

if !ok || content == "" {
for key, value := range aliasData {
prefix := key[:1]

bodyData["message"], bodyData = getMessage(messageAliases, bodyData)
keyWithoutPrefix := key[1:]

modifiedBody = true
switch prefix {
case "@":
bodyData[keyWithoutPrefix] = value
modifiedBody = true
case ".":
settings.VARIABLES[keyWithoutPrefix] = value
}
}
}

Expand All @@ -70,32 +83,44 @@ func (data BodyMiddleware) Use() http.Handler {
})
}

func getMessage(aliases []middlewareTypes.MessageAlias, data map[string]any) (string, map[string]any) {
var content string
func processDataAliases(aliases map[string][]middlewareTypes.DataAlias, data map[string]any) (map[string]any) {
aliasData := map[string]any{}

for key, alias := range aliases {
key, value := getData(key, alias, data)

aliasData[key] = value
}

return aliasData
}

func getData(key string, aliases []middlewareTypes.DataAlias, data map[string]any) (string, any) {
var best int
var value any

for _, alias := range aliases {
aliasValue, score, ok := processAlias(alias, data)

if ok && score > best {
content = aliasValue
}
if ok {
if score > best {
value = aliasValue
}

data[alias.Alias] = nil
data[alias.Alias] = nil
}
}

return content, data
return key, value
}

func processAlias(alias middlewareTypes.MessageAlias, data map[string]any) (string, int, bool) {
func processAlias(alias middlewareTypes.DataAlias, data map[string]any) (any, int, bool) {
aliasKey := alias.Alias

value, ok := jsonutils.GetByPath(aliasKey, data)

aliasValue, isStr := value.(string)

if isStr && ok && aliasValue != "" {
return aliasValue, alias.Score, true
if ok && value != nil {
return value, alias.Score, true
} else {
return "", 0, false
}
Expand Down
Loading