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
|
||||||
|
|
||||||
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`.
|
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
|
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 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
|
||||||
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
|
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 (
|
import (
|
||||||
"crypto/md5"
|
"crypto/md5"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
|
"flag"
|
||||||
"image"
|
"image"
|
||||||
"image/color"
|
"image/color"
|
||||||
"image/draw"
|
"image/draw"
|
||||||
@ -14,6 +15,7 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/BurntSushi/toml"
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -133,12 +135,24 @@ func RequestHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
colorScheme := r.URL.Query().Get("c")
|
colorScheme := r.URL.Query().Get("c")
|
||||||
if colorScheme == "" {
|
if colorScheme == "" {
|
||||||
colorScheme = os.Getenv("COLORSCHEME")
|
colorScheme = config.Defaults.ColorScheme
|
||||||
}
|
}
|
||||||
|
|
||||||
pattern := r.URL.Query().Get("d")
|
pattern := r.URL.Query().Get("d")
|
||||||
if pattern == "" {
|
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")
|
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() {
|
func main() {
|
||||||
|
configFile := flag.String("c", "/etc/idicon/config.toml", "-c <path to config file>")
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
configure(*configFile)
|
||||||
|
|
||||||
router := mux.NewRouter()
|
router := mux.NewRouter()
|
||||||
router.HandleFunc("/avatar/{id}", RequestHandler)
|
router.HandleFunc("/avatar/{id}", RequestHandler)
|
||||||
log.Println("Starting ...")
|
log.Println("Starting ...")
|
||||||
|
@ -6,6 +6,7 @@ import (
|
|||||||
"image/png"
|
"image/png"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
|
"os"
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
@ -19,7 +20,10 @@ var v1 []byte
|
|||||||
var v2 []byte
|
var v2 []byte
|
||||||
|
|
||||||
//go:embed testdata/1a79a4d60de6718e8e5b326e338ae533_gh.png
|
//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 {
|
func testRouter() *mux.Router {
|
||||||
router := mux.NewRouter()
|
router := mux.NewRouter()
|
||||||
@ -78,7 +82,7 @@ func TestCorrectResponseForGHColorSchemeAndPattern(t *testing.T) {
|
|||||||
rr := httptest.NewRecorder()
|
rr := httptest.NewRecorder()
|
||||||
testRouter().ServeHTTP(rr, req)
|
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")
|
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) {
|
func TestHSLtoRGB(t *testing.T) {
|
||||||
red := hslToRgba(0, 100, 50)
|
red := hslToRgba(0, 100, 50)
|
||||||
if red.R != 255 || red.G != 0 || red.B != 0 {
|
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