mirror of
https://github.com/pcvolkmer/idicon.git
synced 2025-04-19 16:46:50 +00:00
Add TOML based config file
The config file may provide default values or user sepcific settings.
This commit is contained in:
parent
d20eb306fd
commit
fdc344d6d6
31
README.adoc
31
README.adoc
@ -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
7
go.mod
@ -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
2
go.sum
@ -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=
|
||||
|
65
idicon.go
65
idicon.go
@ -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 ...")
|
||||
|
@ -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 {
|
||||
|
BIN
testdata/a1d0c6e83f027327d8461063f4ac58a6_gh.png
vendored
Normal file
BIN
testdata/a1d0c6e83f027327d8461063f4ac58a6_gh.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 266 B |
8
testdata/testconfig.toml
vendored
Normal file
8
testdata/testconfig.toml
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
[defaults]
|
||||
color-scheme = "gh"
|
||||
|
||||
[[users]]
|
||||
id = "example"
|
||||
alias = "42"
|
||||
color-scheme = "gh"
|
||||
pattern = "github"
|
Loading…
x
Reference in New Issue
Block a user