Add TOML based config file

The config file may provide default values or user sepcific settings.
This commit is contained in:
Paul-Christian Volkmer 2022-01-13 08:43:05 +01:00
parent d20eb306fd
commit fdc344d6d6
7 changed files with 157 additions and 7 deletions

View File

@ -21,7 +21,36 @@ The request query parameter `d` can be used to request GitHub like patterns by s
=== Configuration
Configuration is available by using environment variables.
Configuration is available by using a config file or by using environment variables.
==== Config file
If config file `/etc/identicon/config.toml` exists, its configuration will be used on application start.
Use application argument `-c` to use another file.
....
$ identicon -c ./config.toml
....
In addition to configuration for default values, the configuration file can also be used to create specific configs for users.
....
[defaults]
color-scheme = "v2" # Default color scheme
[[users]]
id = "me@example.com" # The users ID in plain text
alias = "42" # The alias to be used, e.g. for mapping users to other IDs
color-scheme = "gh" # The color scheme to be used for this user
pattern = "github" # The pattern to be used for this user
[[users]]
...
....
If config file is not present, the application will ignore it. Using environment variables will override default settings.
==== Environment Variables
You can use `COLORSCHEME` to define the default color scheme to be used. Fallback value will be `v2`.

7
go.mod
View File

@ -1,5 +1,8 @@
module idicon
go 1.16
go 1.17
require github.com/gorilla/mux v1.8.0
require (
github.com/BurntSushi/toml v1.0.0
github.com/gorilla/mux v1.8.0
)

2
go.sum
View File

@ -1,2 +1,4 @@
github.com/BurntSushi/toml v1.0.0 h1:dtDWrepsVPfW9H/4y7dDgFc2MBUSeJhlaDtK13CxFlU=
github.com/BurntSushi/toml v1.0.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=

View File

@ -3,6 +3,7 @@ package main
import (
"crypto/md5"
"encoding/hex"
"flag"
"image"
"image/color"
"image/draw"
@ -14,6 +15,7 @@ import (
"strconv"
"strings"
"github.com/BurntSushi/toml"
"github.com/gorilla/mux"
)
@ -133,12 +135,24 @@ func RequestHandler(w http.ResponseWriter, r *http.Request) {
colorScheme := r.URL.Query().Get("c")
if colorScheme == "" {
colorScheme = os.Getenv("COLORSCHEME")
colorScheme = config.Defaults.ColorScheme
}
pattern := r.URL.Query().Get("d")
if pattern == "" {
pattern = os.Getenv("PATTERN")
pattern = config.Defaults.Pattern
}
for _, userConfig := range config.Users {
if hashBytes(id) == hashBytes(userConfig.Id) {
id = userConfig.Alias
if len(userConfig.ColorScheme) > 0 {
colorScheme = userConfig.ColorScheme
}
if len(userConfig.Pattern) > 0 {
pattern = userConfig.Pattern
}
}
}
w.Header().Add("Content-Type", "image/png")
@ -157,7 +171,54 @@ func RequestHandler(w http.ResponseWriter, r *http.Request) {
}
type Config struct {
Defaults Defaults `toml:"defaults"`
Users []UserConfig `toml:"users"`
}
type Defaults struct {
ColorScheme string `toml:"color-scheme"`
Pattern string `toml:"pattern"`
}
type UserConfig struct {
Id string `toml:"id"`
Alias string `toml:"alias"`
ColorScheme string `toml:"color-scheme"`
Pattern string `toml:"pattern"`
}
var (
config Config
)
func configure(configFile string) {
if file, err := os.OpenFile(configFile, os.O_RDONLY, 0); err == nil {
c := &Config{}
_, err := toml.NewDecoder(file).Decode(c)
if err != nil {
log.Printf("Invalid config file '%s' - ignore it.\n", configFile)
}
defer file.Close()
config = *c
}
if os.Getenv("COLORSCHEME") != "" {
config.Defaults.ColorScheme = os.Getenv("COLORSCHEME")
}
if os.Getenv("PATTERN") != "" {
config.Defaults.Pattern = os.Getenv("PATTERN")
}
}
func main() {
configFile := flag.String("c", "/etc/idicon/config.toml", "-c <path to config file>")
flag.Parse()
configure(*configFile)
router := mux.NewRouter()
router.HandleFunc("/avatar/{id}", RequestHandler)
log.Println("Starting ...")

View File

@ -6,6 +6,7 @@ import (
"image/png"
"net/http"
"net/http/httptest"
"os"
"reflect"
"testing"
@ -19,7 +20,10 @@ var v1 []byte
var v2 []byte
//go:embed testdata/1a79a4d60de6718e8e5b326e338ae533_gh.png
var gh []byte
var gh1 []byte
//go:embed testdata/a1d0c6e83f027327d8461063f4ac58a6_gh.png
var gh2 []byte
func testRouter() *mux.Router {
router := mux.NewRouter()
@ -78,7 +82,7 @@ func TestCorrectResponseForGHColorSchemeAndPattern(t *testing.T) {
rr := httptest.NewRecorder()
testRouter().ServeHTTP(rr, req)
if !reflect.DeepEqual(rr.Body.Bytes(), gh) {
if !reflect.DeepEqual(rr.Body.Bytes(), gh1) {
t.Errorf("returned image does not match expected image")
}
}
@ -108,6 +112,49 @@ func TestStringMatchesHash(t *testing.T) {
}
}
func TestUsesConfig(t *testing.T) {
configure("./testdata/testconfig.toml")
if config.Defaults.ColorScheme != "gh" ||
config.Users[0].Id != "example" ||
config.Users[0].Alias != "42" ||
config.Users[0].ColorScheme != "gh" ||
config.Users[0].Pattern != "github" {
t.Errorf("Config not applied as expected")
}
}
func TestUsesConfigWithEnvVar(t *testing.T) {
os.Setenv("COLORSCHEME", "v1")
os.Setenv("PATTERN", "default")
configure("./testdata/testconfig.toml")
if config.Defaults.ColorScheme != "v1" ||
config.Users[0].Id != "example" ||
config.Users[0].Alias != "42" ||
config.Users[0].ColorScheme != "gh" ||
config.Users[0].Pattern != "github" {
t.Errorf("Config not applied as expected")
}
}
func TestCorrectResponseForUserConfig(t *testing.T) {
configure("./testdata/testconfig.toml")
req, err := http.NewRequest("GET", "/avatar/example", nil)
if err != nil {
t.Fatal(err)
}
rr := httptest.NewRecorder()
testRouter().ServeHTTP(rr, req)
if !reflect.DeepEqual(rr.Body.Bytes(), gh2) {
t.Errorf("returned image does not match expected image for mapped alias '42'")
}
}
func TestHSLtoRGB(t *testing.T) {
red := hslToRgba(0, 100, 50)
if red.R != 255 || red.G != 0 || red.B != 0 {

Binary file not shown.

After

Width:  |  Height:  |  Size: 266 B

8
testdata/testconfig.toml vendored Normal file
View File

@ -0,0 +1,8 @@
[defaults]
color-scheme = "gh"
[[users]]
id = "example"
alias = "42"
color-scheme = "gh"
pattern = "github"