Skip to content

Commit

Permalink
Add Steuerbare und Technische Ressource (#137)
Browse files Browse the repository at this point in the history
* WIP Add Steuerbare and technische Ressource to generators

* All ids version with seperate checksums and confetti, not tested

* update readme with actual URLs

* fix build errors

* fix tests by renaming

* fix docstring

* fix links to newly created azure ressources

somehow lower case g now

* extend readme

* fix: "go: cannot write multiple packages to non-directory api"

go build -o api cmd
go: cannot write multiple packages to non-directory api

* wip

* fix key words in all-ids page

* delete all-ids for now (not ready yet)

cherry picked to another branch: bed5be6

---------

Co-authored-by: konstantin <konstantin.klein@hochfrequenz.de>
Co-authored-by: Konstantin <konstantin.klein+github@hochfrequenz.de>
  • Loading branch information
3 people authored Sep 20, 2024
1 parent 21b2373 commit 07d4f0f
Show file tree
Hide file tree
Showing 6 changed files with 177 additions and 11 deletions.
33 changes: 24 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
* [markt.lokations.id](https://markt.lokations.id), einem Generator für Marktlokations-IDs ("MaLo-ID") zu Testzwecken
* [netz.lokations.id](https://netz.lokations.id), einem Generator für Netzlokations-IDs ("NeLo-ID") zu Testzwecken
* [mess.lokations.id](https://mess.lokations.id), einem Generator für Messlokations-IDs ("MeLo-ID") zu Testzwecken
* [technische.ressource.id](https://techniscche.ressource.id), einem Generator für Technische Ressourcen-IDs ("TR-ID") zu Testzwecken
* [steuerbare.ressource.id](https://steuerbare.ressource.id), einem Generator für Steuerbare Ressourcen-IDs ("SR-ID") zu Testzwecken

🇬🇧 This repository contains
an [Azure Function with a Go Handler](https://docs.microsoft.com/en-us/azure/azure-functions/create-first-function-vs-code-other?tabs=go%2Cwindows) which is deployed to [netz.lokations.id](https://netz.lokations.id) and [markt.lokations.id](https://markt.lokations.id).
Expand All @@ -17,7 +19,9 @@ Its purpose is to
- generate:
1. Marktlokations-IDs (MaLo-IDs)
2. Netzlokations-IDs (NeLo-IDs)
3. Messlokations-IDs (NeLo-IDs)
3. Messlokations-IDs (MeLo-IDs)
4. Technische Ressourcen-IDs (TR-IDs)
5. Steuerbare Ressourcen-IDs (SR-IDs)
- with a valid checksum
- on the fly

Expand Down Expand Up @@ -59,19 +63,21 @@ Both Function apps are assigned to the [malo-id-generator resource group on Azur
There is one function app instance per supported ID type.
This is because to use the function app directly behind top level domain registered in Azure, its respective entry point must be a top level domain itself without any further, relative path (e.g. `foobarsomerandomstring.azurewebsites.net` and _not_ `foobarsomerandomstring.azurewebsites.net/malo`).

| Purpose | `ID_TYPE_TO_GENERATE` env var value | Deployed to (URL) | Settings |
|-------------------|-------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Generate MaLo-IDs | `"MALO"` | [`malo-id-generator.azurewebsites.net/`](https://malo-id-generator.azurewebsites.net/) and [markt.lokations.id](https://markt.lokations.id) | [malo-id-generator](https://portal.azure.com/#@hochfrequenz.net/resource/subscriptions/1cdc65f0-62d2-4770-be11-9ec1da950c81/resourceGroups/malo-id-generator/providers/Microsoft.Web/sites/malo-id-generator/appServices) | |.
| Generate NeLo-IDs | `"NELO"` | [`nelo-id-generator.azurewebsites.net/`](https://nelo-id-generator.azurewebsites.net/) and [netz.lokations.id](https://netz.lokations.id) | [nelo-id-generator](https://portal.azure.com/#@hochfrequenz.net/resource/subscriptions/1cdc65f0-62d2-4770-be11-9ec1da950c81/resourcegroups/malo-id-generator/providers/Microsoft.Web/sites/nelo-id-generator/appServices) |
| Generate MeLo-IDs | `"MELO"` | [`melo-id-generator.azurewebsites.net/`](https://melo-id-generator.azurewebsites.net/) and [mess.lokations.id](https://mess.lokations.id) | [melo-id-generator](https://portal.azure.com/#@hochfrequenz.net/resource/subscriptions/1cdc65f0-62d2-4770-be11-9ec1da950c81/resourceGroups/malo-id-generator/providers/Microsoft.Web/sites/melo-id-generator/appServices) |
| Purpose | `ID_TYPE_TO_GENERATE` env var value | Deployed to (URL) | Settings |
|-------------------|-------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Generate MaLo-IDs | `"MALO"` | [`malo-id-generator.azurewebsites.net/`](https://malo-id-generator.azurewebsites.net/) and [markt.lokations.id](https://markt.lokations.id) | [malo-id-generator](https://portal.azure.com/#@hochfrequenz.net/resource/subscriptions/1cdc65f0-62d2-4770-be11-9ec1da950c81/resourceGroups/malo-id-generator/providers/Microsoft.Web/sites/malo-id-generator/appServices) | |.
| Generate NeLo-IDs | `"NELO"` | [`nelo-id-generator.azurewebsites.net/`](https://nelo-id-generator.azurewebsites.net/) and [netz.lokations.id](https://netz.lokations.id) | [nelo-id-generator](https://portal.azure.com/#@hochfrequenz.net/resource/subscriptions/1cdc65f0-62d2-4770-be11-9ec1da950c81/resourcegroups/malo-id-generator/providers/Microsoft.Web/sites/nelo-id-generator/appServices) |
| Generate MeLo-IDs | `"MELO"` | [`melo-id-generator.azurewebsites.net/`](https://melo-id-generator.azurewebsites.net/) and [mess.lokations.id](https://mess.lokations.id) | [melo-id-generator](https://portal.azure.com/#@hochfrequenz.net/resource/subscriptions/1cdc65f0-62d2-4770-be11-9ec1da950c81/resourceGroups/malo-id-generator/providers/Microsoft.Web/sites/melo-id-generator/appServices) |
| Generate TR-IDs | `"TRID"` | [`tr-id-generator.azurewebsites.net/`](https://tr-id-generator.azurewebsites.net/) and [technische.ressource.id](https://technische.ressource.id) | [tr-id-generator](https://portal.azure.com/#@hochfrequenz.net/resource/subscriptions/1cdc65f0-62d2-4770-be11-9ec1da950c81/resourcegroups/malo-id-generator/providers/Microsoft.Web/sites/tr-id-generator/appServices) |
| Generate SR-IDs | `"SRID"` | [`sr-id-generator.azurewebsites.net/`](https://sr-id-generator.azurewebsites.net/) and [steuerbare.ressource.id](https://steuerbare.ressource.id) | [sr-id-generator](https://portal.azure.com/#@hochfrequenz.net/resource/subscriptions/1cdc65f0-62d2-4770-be11-9ec1da950c81/resourcegroups/malo-id-generator/providers/Microsoft.Web/sites/sr-id-generator/appServices) |

The function apps are all

- code based (instead of dockerized (todo @kevin))
- linux based (instead of windows)

There is an environment variable named `ID_TYPE_TO_GENERATE` which you can modify in the [function app settings](https://portal.azure.com/#@hochfrequenz.net/resource/subscriptions/1cdc65f0-62d2-4770-be11-9ec1da950c81/resourcegroups/malo-id-generator/providers/Microsoft.Web/sites/malo-id-generator/configuration).
Its value can only be `"MALO"` or `"NELO"` or `"MELO"` at the moment.
Its value can be `"MALO"` or `"NELO"` or `"MELO"` or `"TRID"` or `"SRID"`at the moment.
If its value is not set or set to an invalid value, the function app will return a HTTP 501 error.
For your local tests you can modify the value in the `local.settings.json` file.

Expand All @@ -85,7 +91,7 @@ First **build** locally for linux (note that the build is the same for all ID ty

```bash
set GOOS=linux
go build -o api cmd/
go build -o api ./cmd
```

The GOOS env var can be set in the build configuration in Goland.
Expand All @@ -100,6 +106,15 @@ or
```bash
func azure functionapp publish nelo-id-generator
```
respectively.
respectively (and similar for `melo-id-generator`, `sr-id-generator` and `tr-id-generator`).

You have to be logged in (`az login`) using the [Azure CLI Tools](https://docs.microsoft.com/de-de/cli/azure/install-azure-cli-windows?tabs=azure-cli).

#### Deploy them all
```bash
func azure functionapp publish malo-id-generator
func azure functionapp publish melo-id-generator
func azure functionapp publish nelo-id-generator
func azure functionapp publish sr-id-generator
func azure functionapp publish tr-id-generator
```
10 changes: 8 additions & 2 deletions cmd/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,15 @@ func getIdGenerator() (IdGenerator, error) {
if idTypeToGenerate == "MELO" {
return MeLoIdGenerator{}, nil
}
return nil, fmt.Errorf("unsupported value of environment variable 'ID_TYPE_TO_GENERATE': '%s'. Supported values are 'MALO' and 'NELO'.", idTypeToGenerate)
if idTypeToGenerate == "TRID" {
return TRIdGenerator{}, nil
}
if idTypeToGenerate == "SRID" {
return SRIdGenerator{}, nil
}
return nil, fmt.Errorf("unsupported value of environment variable 'ID_TYPE_TO_GENERATE': '%s'. Supported values are 'MALO', 'NELO', 'MELO', .", idTypeToGenerate)
}
return nil, fmt.Errorf("no value set for environment variable 'ID_TYPE_TO_GENERATE'. Supported values are 'MALO', 'NELO' and 'MELO'.")
return nil, fmt.Errorf("no value set for environment variable 'ID_TYPE_TO_GENERATE'. Supported values are 'MALO', 'NELO', 'MELO', 'TRID' and 'SRID'.")
}

func generateRandomId(c *gin.Context) {
Expand Down
22 changes: 22 additions & 0 deletions cmd/api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,28 @@ func (s *Suite) Test_MeLo_Endpoint_Returns_Something_Like_A_MeLo() {
then.AssertThat(s.T(), containsDe, is.True())
}

func (s *Suite) Test_TRID_Endpoint_Returns_Something_Like_A_TRID() {
err := os.Setenv("ID_TYPE_TO_GENERATE", "trid")
then.AssertThat(s.T(), err, is.Nil())
tridPattern := regexp.MustCompile(`D[A-Z\d]{9}<span [^>]+>\d</span>`)
router := main.NewRouter()
response := performGetRequest(router, "/")
then.AssertThat(s.T(), response.Code, is.EqualTo(http.StatusOK))
responseBody := response.Body.String()
then.AssertThat(s.T(), tridPattern.MatchString(responseBody), is.True())
}

func (s *Suite) Test_SRID_Endpoint_Returns_Something_Like_A_SRID() {
err := os.Setenv("ID_TYPE_TO_GENERATE", "srid")
then.AssertThat(s.T(), err, is.Nil())
sridPattern := regexp.MustCompile(`C[A-Z\d]{9}<span [^>]+>\d</span>`)
router := main.NewRouter()
response := performGetRequest(router, "/")
then.AssertThat(s.T(), response.Code, is.EqualTo(http.StatusOK))
responseBody := response.Body.String()
then.AssertThat(s.T(), sridPattern.MatchString(responseBody), is.True())
}

func (s *Suite) Test_Stylesheet_Is_Returned() {
router := main.NewRouter()
response := performGetRequest(router, "/style")
Expand Down
47 changes: 47 additions & 0 deletions cmd/idgenerators.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,3 +138,50 @@ func (m MeLoIdGenerator) GenerateId(c *gin.Context) {
})
log.Printf("Successfully generated the MeLo '%s'", meloId)
}

// Ressourcen-IDs

// allowedRessourcenIdCharacters contains those characters that are used to create new "Technische Ressourcen-IDs" and "Steuerbare Ressourcen-IDs"
var allowedRessourcenIdCharacters = []rune("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ")

// TRIdGenerator is an IdGenerator that generates TR-IDs (Technische Ressourcen-IDs)
type TRIdGenerator struct{}

// GenerateId of the TRIdGenerator returns a new random, 11 digit tr-id that has a valid check sum
func (m TRIdGenerator) GenerateId(c *gin.Context) {
var trIdWithoutChecksum = "D" + generateRandomString(allowedRessourcenIdCharacters, 9)
_checksum, err := bo.GetTRIdCheckSum(trIdWithoutChecksum)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
var trIdChecksum = fmt.Sprintf("%d", _checksum)
trId := trIdWithoutChecksum + trIdChecksum
c.HTML(http.StatusOK, "static/templates/trid.tmpl.html", gin.H{
"trIdWithoutChecksum": trIdWithoutChecksum,
"checksum": trIdChecksum,
"recruitingMessage": template.HTML(recruitingMessage),
})
log.Printf("Successfully generated the TRID '%s'", trId)
}

// SRIdGenerator is an IdGenerator that generates SR-IDs (Steuerbare Ressourcen-IDs)
type SRIdGenerator struct{}

// GenerateId of the SRIdGenerator returns a new random, 11 digit sr-id that has a valid check sum
func (m SRIdGenerator) GenerateId(c *gin.Context) {
var srIdWithoutChecksum = "C" + generateRandomString(allowedRessourcenIdCharacters, 9)
_checksum, err := bo.GetSRIdCheckSum(srIdWithoutChecksum)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
var srIdChecksum = fmt.Sprintf("%d", _checksum)
srId := srIdWithoutChecksum + srIdChecksum
c.HTML(http.StatusOK, "static/templates/srid.tmpl.html", gin.H{
"srIdWithoutChecksum": srIdWithoutChecksum,
"checksum": srIdChecksum,
"recruitingMessage": template.HTML(recruitingMessage),
})
log.Printf("Successfully generated the SRID '%s'", srId)
}
38 changes: 38 additions & 0 deletions cmd/static/templates/srid.tmpl.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="utf-8">
<title>Steuerbare Ressource Id-Generator (zufällige SR-IDs)</title>
<meta name="author" content="Hochfrequenz Unternehmensberatung GmbH">
<meta name="description" content="Zufällig generierte SR-IDs mit gültiger Prüfziffer">
<meta name="keywords" content="SR, SR-ID, Steuerbare Ressource, Test, Test-SR-ID, Steuerbare Ressourcen-ID (SR-ID)">
<meta http-equiv="cache-control" content="no-cache"/>
<!-- prevent safari from formatting numbers with good intentions: https://stackoverflow.com/a/30426346/10009545 -->
<meta name="format-detection" content="telephone=no"/>
<link rel="stylesheet" href="/style">
<link rel="icon" type="image/x-icon" href="/favicon">
<script>
function copyToClipboard() {
var textToCopy = document.querySelector('#content h1').textContent.trim();
navigator.clipboard.writeText(textToCopy)
.then(function () {
// alert('Text copied to clipboard: ' + textToCopy); // thanks, chatgpt, we don't need the alert ;)
})
.catch(function (err) {
console.error('Error copying text to clipboard: ', err);
});
}
</script>
</head>
<body class="whiteBackground">
{{ .recruitingMessage }}<!-- We pass the HTML comment / recruiting ad as a parameter because the HTML comment was stripped from the template -->
<div id="content">
<h1 class="{{ .issuer }}" title="Eine zufällige Steuerbare Ressourcen-ID mit gültiger Prüfziffer"><div>{{
.srIdWithoutChecksum }}<span class="checksum" title="Prüfziffer {{ .checksum }}">{{ .checksum }}</span></div>
</h1>
<button onclick="copyToClipboard()">&#128203; Copy</button>
</div>
<br style="clear:both" />
<div id="footer">powered by <a href="https://hochfrequenz.de/">hochfrequenz</a> | <a href="https://www.hochfrequenz.de/impressum/">Impressum</a> | <a href="https://github.com/Hochfrequenz/malo-id-generator">GitHub</a></div>
</body>
</html>
38 changes: 38 additions & 0 deletions cmd/static/templates/trid.tmpl.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="utf-8">
<title>Technische Ressource Id-Generator (zufällige TR-IDs)</title>
<meta name="author" content="Hochfrequenz Unternehmensberatung GmbH">
<meta name="description" content="Zufällig generierte TR-IDs mit gültiger Prüfziffer">
<meta name="keywords" content="TR, TR-ID, Technische Ressource, Test, Test-TR-ID, Technische Ressourcen-ID (TR-ID)">
<meta http-equiv="cache-control" content="no-cache"/>
<!-- prevent safari from formatting numbers with good intentions: https://stackoverflow.com/a/30426346/10009545 -->
<meta name="format-detection" content="telephone=no"/>
<link rel="stylesheet" href="/style">
<link rel="icon" type="image/x-icon" href="/favicon">
<script>
function copyToClipboard() {
var textToCopy = document.querySelector('#content h1').textContent.trim();
navigator.clipboard.writeText(textToCopy)
.then(function () {
// alert('Text copied to clipboard: ' + textToCopy); // thanks, chatgpt, we don't need the alert ;)
})
.catch(function (err) {
console.error('Error copying text to clipboard: ', err);
});
}
</script>
</head>
<body class="whiteBackground">
{{ .recruitingMessage }}<!-- We pass the HTML comment / recruiting ad as a parameter because the HTML comment was stripped from the template -->
<div id="content">
<h1 class="{{ .issuer }}" title="Eine zufällige Technische Ressourcen-ID mit gültiger Prüfziffer"><div>{{
.trIdWithoutChecksum }}<span class="checksum" title="Prüfziffer {{ .checksum }}">{{ .checksum }}</span></div>
</h1>
<button onclick="copyToClipboard()">&#128203; Copy</button>
</div>
<br style="clear:both" />
<div id="footer">powered by <a href="https://hochfrequenz.de/">hochfrequenz</a> | <a href="https://www.hochfrequenz.de/impressum/">Impressum</a> | <a href="https://github.com/Hochfrequenz/malo-id-generator">GitHub</a></div>
</body>
</html>

0 comments on commit 07d4f0f

Please sign in to comment.