mirror of
https://github.com/TecharoHQ/anubis.git
synced 2025-10-04 05:41:59 +08:00
* feat(lib/challenge): expose ResponseWriter to challenge issuers Signed-off-by: Xe Iaso <me@xeiaso.net> * feat(metarefresh): randomly use the Refresh header There are several ways to trigger an automatic refresh without JavaScript. One of them is the "meta refresh" method[1], but the other is with the Refresh header[2]. Both are semantically identical and supported with browsers as old as Chrome version 1. Given that they are basically the same thing, this patch makes Anubis randomly select between them by using the challenge random data's first character. This will fire about 50% of the time. I expect this to have no impact. If this works out fine, then I will implement some kind of fallback logic for the fast challenge such that admins can opt into allowing clients with a no-js configuration to pass the fast challenge. This needs to bake in the oven though. [1]: https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/meta/http-equiv [2]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Refresh Signed-off-by: Xe Iaso <me@xeiaso.net> * docs: update CHANGELOG Signed-off-by: Xe Iaso <me@xeiaso.net> * feat(metarefresh): simplify random logic Signed-off-by: Xe Iaso <me@xeiaso.net> --------- Signed-off-by: Xe Iaso <me@xeiaso.net> Signed-off-by: Xe Iaso <xe.iaso@techaro.lol>
68 lines
1.4 KiB
Go
68 lines
1.4 KiB
Go
package challenge
|
|
|
|
import (
|
|
"log/slog"
|
|
"net/http"
|
|
"sort"
|
|
"sync"
|
|
|
|
"github.com/TecharoHQ/anubis/lib/policy"
|
|
"github.com/TecharoHQ/anubis/lib/policy/config"
|
|
"github.com/TecharoHQ/anubis/lib/store"
|
|
"github.com/a-h/templ"
|
|
)
|
|
|
|
var (
|
|
registry map[string]Impl = map[string]Impl{}
|
|
regLock sync.RWMutex
|
|
)
|
|
|
|
func Register(name string, impl Impl) {
|
|
regLock.Lock()
|
|
defer regLock.Unlock()
|
|
|
|
registry[name] = impl
|
|
}
|
|
|
|
func Get(name string) (Impl, bool) {
|
|
regLock.RLock()
|
|
defer regLock.RUnlock()
|
|
result, ok := registry[name]
|
|
return result, ok
|
|
}
|
|
|
|
func Methods() []string {
|
|
regLock.RLock()
|
|
defer regLock.RUnlock()
|
|
var result []string
|
|
for method := range registry {
|
|
result = append(result, method)
|
|
}
|
|
sort.Strings(result)
|
|
return result
|
|
}
|
|
|
|
type IssueInput struct {
|
|
Impressum *config.Impressum
|
|
Rule *policy.Bot
|
|
Challenge *Challenge
|
|
OGTags map[string]string
|
|
Store store.Interface
|
|
}
|
|
|
|
type ValidateInput struct {
|
|
Rule *policy.Bot
|
|
Challenge *Challenge
|
|
Store store.Interface
|
|
}
|
|
|
|
type Impl interface {
|
|
// Setup registers any additional routes with the Impl for assets or API routes.
|
|
Setup(mux *http.ServeMux)
|
|
|
|
// Issue a new challenge to the user, called by the Anubis.
|
|
Issue(w http.ResponseWriter, r *http.Request, lg *slog.Logger, in *IssueInput) (templ.Component, error)
|
|
|
|
// Validate a challenge, making sure that it passes muster.
|
|
Validate(r *http.Request, lg *slog.Logger, in *ValidateInput) error
|
|
}
|