feature (api): api configuration

This commit is contained in:
Mickael Kerjean 2022-09-07 00:50:23 +10:00
parent 3a63eb0777
commit b1c1f9e0f2
3 changed files with 79 additions and 7 deletions

View file

@ -2,11 +2,72 @@ package common
import (
"os"
"regexp"
"strings"
)
func IsApiKeyValid(api_key string) bool {
if api_key == os.Getenv("API_KEY") {
return true
var (
isApiEnabled func() bool
getApiKey func() string
)
func init() {
isApiEnabled = func() bool {
return Config.Get("features.api.enabled").Schema(func(f *FormElement) *FormElement {
if f == nil {
f = &FormElement{}
}
f.Name = "enabled"
f.Type = "boolean"
f.Description = "Enable/Disable the API"
f.Default = true
return f
}).Bool()
}
return false
getApiKey = func() string {
return Config.Get("features.api.api_key").Schema(func(f *FormElement) *FormElement {
if f == nil {
f = &FormElement{}
}
f.Name = "api_key"
f.Type = "long_text"
f.Description = "Format: '[mandatory:key] [optional:hostname]'. The hostname is used to enabled CORS for your application."
f.Placeholder = "foobar *.filestash.app"
return f
}).String()
}
go func() {
select {
case <-Config.Event:
isApiEnabled()
getApiKey()
}
}()
}
func VerifyApiKey(api_key string) (host string, err error) {
if isApiEnabled() == false {
return "", NewError("Api is not enabled", 503)
} else if api_key == os.Getenv("API_KEY") {
return "*", nil
}
lines := strings.Split(getApiKey(), "\n")
for _, line := range lines {
line = regexp.MustCompile(` #.*`).ReplaceAllString(line, "") // remove comment
chunks := strings.SplitN(line, " ", 2)
if len(chunks) == 0 {
continue
} else if chunks[0] != api_key {
continue
}
if len(chunks) == 1 {
return "", nil
}
chunks[1] = strings.TrimSpace(chunks[1])
if chunks[1] == "" {
return "*", nil
}
return chunks[1], nil
}
return "", ErrNotValid
}

View file

@ -23,6 +23,7 @@ type Configuration struct {
cache KeyValueStore
form []Form
Conn []map[string]interface{}
Event chan string
}
type Form struct {
@ -52,6 +53,7 @@ func init() {
Config = NewConfiguration()
Config.Load()
Config.Initialise()
Config.Event <- "init"
}
func NewConfiguration() Configuration {
@ -84,6 +86,10 @@ func NewConfiguration() Configuration {
Form{
Title: "features",
Form: []Form{
Form{
Title: "api",
Elmnts: []FormElement{},
},
Form{
Title: "share",
Elmnts: []FormElement{
@ -125,7 +131,8 @@ func NewConfiguration() Configuration {
},
},
},
Conn: make([]map[string]interface{}, 0),
Conn: make([]map[string]interface{}, 0),
Event: make(chan string),
}
}

View file

@ -279,9 +279,13 @@ func _extractSession(req *http.Request, ctx *App) (map[string]string, error) {
if err != nil {
return session, err
}
if IsApiKeyValid(session["api_key"]) == false {
if _, err := VerifyApiKey(session["api_key"]); err != nil {
Log.Warning("attempt to use a non valid api key %s", session["api_key"])
return session, ErrNotValid
if err == ErrNotValid {
return session, NewError("Your API key is not valid", 401)
} else {
return session, err
}
} else if t.Add(EXPIRATION_API_TOKEN * time.Second).Before(time.Now()) {
return session, NewError("Access Token has expired", 401)
}