diff --git a/docs/docs/CHANGELOG.md b/docs/docs/CHANGELOG.md
index 68fb43d..5f37f5a 100644
--- a/docs/docs/CHANGELOG.md
+++ b/docs/docs/CHANGELOG.md
@@ -27,6 +27,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Legacy JavaScript code has been eliminated.
- The contact email in the LibreJS header has been changed.
- The hard dependency on WebCrypto has been removed, allowing a proof of work challenge to work over plain (unencrypted) HTTP.
+- Firefox for Android support has been fixed by embedding the challenge ID into the pass-challenge route. This also fixes some inconsistent issues with other mobile browsers.
+- The Anubis version number is put in the footer of every page.
### Breaking changes
diff --git a/lib/anubis.go b/lib/anubis.go
index b9eba5f..9321f2b 100644
--- a/lib/anubis.go
+++ b/lib/anubis.go
@@ -92,15 +92,10 @@ func (s *Server) getTokenKeyfunc() jwt.Keyfunc {
}
func (s *Server) getChallenge(r *http.Request) (*challenge.Challenge, error) {
- ckies := r.CookiesNamed(anubis.TestCookieName)
- if len(ckies) == 0 {
- return nil, store.ErrNotFound
- }
-
+ id := r.FormValue("id")
j := store.JSON[challenge.Challenge]{Underlying: s.store}
- ckie := ckies[0]
- chall, err := j.Get(r.Context(), "challenge:"+ckie.Value)
+ chall, err := j.Get(r.Context(), "challenge:"+id)
return &chall, err
}
diff --git a/lib/challenge/metarefresh/metarefresh.go b/lib/challenge/metarefresh/metarefresh.go
index db6fcc6..7655a9d 100644
--- a/lib/challenge/metarefresh/metarefresh.go
+++ b/lib/challenge/metarefresh/metarefresh.go
@@ -9,7 +9,6 @@ import (
"github.com/TecharoHQ/anubis"
"github.com/TecharoHQ/anubis/lib/challenge"
"github.com/TecharoHQ/anubis/lib/localization"
- "github.com/TecharoHQ/anubis/web"
"github.com/a-h/templ"
)
@@ -32,16 +31,14 @@ func (i *Impl) Issue(r *http.Request, lg *slog.Logger, in *challenge.IssueInput)
q := u.Query()
q.Set("redir", r.URL.String())
q.Set("challenge", in.Challenge.RandomData)
+ q.Set("id", in.Challenge.ID)
u.RawQuery = q.Encode()
loc := localization.GetLocalizer(r)
- component, err := web.BaseWithChallengeAndOGTags(loc.T("making_sure_not_bot"), page(u.String(), in.Rule.Challenge.Difficulty, loc), in.Impressum, in.Challenge.RandomData, in.Rule.Challenge, in.OGTags, loc)
- if err != nil {
- return nil, fmt.Errorf("can't render page: %w", err)
- }
+ result := page(u.String(), in.Rule.Challenge.Difficulty, loc)
- return component, nil
+ return result, nil
}
func (i *Impl) Validate(r *http.Request, lg *slog.Logger, in *challenge.ValidateInput) error {
diff --git a/lib/challenge/proofofwork/proofofwork.go b/lib/challenge/proofofwork/proofofwork.go
index a24a4f5..8cd3127 100644
--- a/lib/challenge/proofofwork/proofofwork.go
+++ b/lib/challenge/proofofwork/proofofwork.go
@@ -11,10 +11,11 @@ import (
"github.com/TecharoHQ/anubis/internal"
chall "github.com/TecharoHQ/anubis/lib/challenge"
"github.com/TecharoHQ/anubis/lib/localization"
- "github.com/TecharoHQ/anubis/web"
"github.com/a-h/templ"
)
+//go:generate go tool github.com/a-h/templ/cmd/templ generate
+
func init() {
chall.Register("fast", &Impl{Algorithm: "fast"})
chall.Register("slow", &Impl{Algorithm: "slow"})
@@ -24,18 +25,11 @@ type Impl struct {
Algorithm string
}
-func (i *Impl) Setup(mux *http.ServeMux) {
- /* no implementation required */
-}
+func (i *Impl) Setup(mux *http.ServeMux) {}
func (i *Impl) Issue(r *http.Request, lg *slog.Logger, in *chall.IssueInput) (templ.Component, error) {
loc := localization.GetLocalizer(r)
- component, err := web.BaseWithChallengeAndOGTags(loc.T("making_sure_not_bot"), web.Index(loc), in.Impressum, in.Challenge.RandomData, in.Rule.Challenge, in.OGTags, loc)
- if err != nil {
- return nil, fmt.Errorf("can't render page: %w", err)
- }
-
- return component, nil
+ return page(loc), nil
}
func (i *Impl) Validate(r *http.Request, lg *slog.Logger, in *chall.ValidateInput) error {
diff --git a/lib/challenge/proofofwork/proofofwork.templ b/lib/challenge/proofofwork/proofofwork.templ
new file mode 100644
index 0000000..0187acc
--- /dev/null
+++ b/lib/challenge/proofofwork/proofofwork.templ
@@ -0,0 +1,39 @@
+package proofofwork
+
+import (
+ "github.com/TecharoHQ/anubis"
+ "github.com/TecharoHQ/anubis/lib/localization"
+)
+
+templ page(localizer *localization.SimpleLocalizer) {
+
+

+

+
{ localizer.T("loading") }
+
+
+
+ { localizer.T("why_am_i_seeing") }
+
+ { localizer.T("ai_companies_explanation") }
+
+
+ { localizer.T("anubis_compromise") }
+
+
+ { localizer.T("hack_purpose") }
+
+
+ { localizer.T("jshelter_note") }
+
+
+
+
+
+}
diff --git a/lib/challenge/proofofwork/proofofwork_templ.go b/lib/challenge/proofofwork/proofofwork_templ.go
new file mode 100644
index 0000000..b32bfae
--- /dev/null
+++ b/lib/challenge/proofofwork/proofofwork_templ.go
@@ -0,0 +1,175 @@
+// Code generated by templ - DO NOT EDIT.
+
+// templ: version: v0.3.924
+package proofofwork
+
+//lint:file-ignore SA4006 This context is only used if a nested component is present.
+
+import "github.com/a-h/templ"
+import templruntime "github.com/a-h/templ/runtime"
+
+import (
+ "github.com/TecharoHQ/anubis"
+ "github.com/TecharoHQ/anubis/lib/localization"
+)
+
+func page(localizer *localization.SimpleLocalizer) templ.Component {
+ return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
+ templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
+ if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
+ return templ_7745c5c3_CtxErr
+ }
+ templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
+ if !templ_7745c5c3_IsBuffer {
+ defer func() {
+ templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err == nil {
+ templ_7745c5c3_Err = templ_7745c5c3_BufErr
+ }
+ }()
+ }
+ ctx = templ.InitializeContext(ctx)
+ templ_7745c5c3_Var1 := templ.GetChildren(ctx)
+ if templ_7745c5c3_Var1 == nil {
+ templ_7745c5c3_Var1 = templ.NopComponent
+ }
+ ctx = templ.ClearChildren(ctx)
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "
)
")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var4 string
+ templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(localizer.T("loading"))
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `proofofwork.templ`, Line: 12, Col: 41}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "
")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var6 string
+ templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(localizer.T("why_am_i_seeing"))
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `proofofwork.templ`, Line: 18, Col: 44}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "
")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var7 string
+ templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(localizer.T("ai_companies_explanation"))
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `proofofwork.templ`, Line: 20, Col: 45}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "
")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var8 string
+ templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(localizer.T("anubis_compromise"))
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `proofofwork.templ`, Line: 23, Col: 38}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "
")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var9 string
+ templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(localizer.T("hack_purpose"))
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `proofofwork.templ`, Line: 26, Col: 33}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "
")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var10 string
+ templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(localizer.T("jshelter_note"))
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `proofofwork.templ`, Line: 29, Col: 34}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "
")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ return nil
+ })
+}
+
+var _ = templruntime.GeneratedTemplate
diff --git a/lib/http.go b/lib/http.go
index 4f8ed02..d548f4d 100644
--- a/lib/http.go
+++ b/lib/http.go
@@ -174,13 +174,23 @@ func (s *Server) RenderIndex(w http.ResponseWriter, r *http.Request, cr policy.C
component, err := impl.Issue(r, lg, in)
if err != nil {
- lg.Error("[unexpected] render failed, please open an issue", "err", err) // This is likely a bug in the template. Should never be triggered as CI tests for this.
+ lg.Error("[unexpected] challenge component render failed, please open an issue", "err", err) // This is likely a bug in the template. Should never be triggered as CI tests for this.
s.respondWithError(w, r, fmt.Sprintf("%s \"RenderIndex\"", localizer.T("internal_server_error")))
return
}
- handler := internal.GzipMiddleware(1, internal.NoStoreCache(templ.Handler(
+ page := web.BaseWithChallengeAndOGTags(
+ localizer.T("making_sure_not_bot"),
component,
+ s.policy.Impressum,
+ chall,
+ in.Rule.Challenge,
+ in.OGTags,
+ localizer,
+ )
+
+ handler := internal.GzipMiddleware(1, internal.NoStoreCache(templ.Handler(
+ page,
templ.WithStatus(s.opts.Policy.StatusCodes.Challenge),
)))
handler.ServeHTTP(w, r)
diff --git a/web/index.go b/web/index.go
index ee2042b..c3ba03d 100644
--- a/web/index.go
+++ b/web/index.go
@@ -3,6 +3,7 @@ package web
import (
"github.com/a-h/templ"
+ "github.com/TecharoHQ/anubis/lib/challenge"
"github.com/TecharoHQ/anubis/lib/localization"
"github.com/TecharoHQ/anubis/lib/policy/config"
)
@@ -11,18 +12,14 @@ func Base(title string, body templ.Component, impressum *config.Impressum, local
return base(title, body, impressum, nil, nil, localizer)
}
-func BaseWithChallengeAndOGTags(title string, body templ.Component, impressum *config.Impressum, challenge string, rules *config.ChallengeRules, ogTags map[string]string, localizer *localization.SimpleLocalizer) (templ.Component, error) {
+func BaseWithChallengeAndOGTags(title string, body templ.Component, impressum *config.Impressum, challenge *challenge.Challenge, rules *config.ChallengeRules, ogTags map[string]string, localizer *localization.SimpleLocalizer) templ.Component {
return base(title, body, impressum, struct {
Rules *config.ChallengeRules `json:"rules"`
- Challenge string `json:"challenge"`
+ Challenge any `json:"challenge"`
}{
Challenge: challenge,
Rules: rules,
- }, ogTags, localizer), nil
-}
-
-func Index(localizer *localization.SimpleLocalizer) templ.Component {
- return index(localizer)
+ }, ogTags, localizer)
}
func ErrorPage(msg, mail string, localizer *localization.SimpleLocalizer) templ.Component {
diff --git a/web/index.templ b/web/index.templ
index a018669..65d704c 100644
--- a/web/index.templ
+++ b/web/index.templ
@@ -58,9 +58,7 @@ templ base(title string, body templ.Component, impressum *config.Impressum, chal
}
@templ.JSONScript("anubis_version", anubis.Version)
- if challenge != nil {
- @templ.JSONScript("anubis_challenge", challenge)
- }
+ @templ.JSONScript("anubis_challenge", challenge)
@templ.JSONScript("anubis_base_prefix", anubis.BasePrefix)
@@ -81,6 +79,7 @@ templ base(title string, body templ.Component, impressum *config.Impressum, chal
-- Imprint
}
+ { localizer.T("version_info") } { anubis.Version }
.
@@ -88,40 +87,6 @@ templ base(title string, body templ.Component, impressum *config.Impressum, chal
}
-templ index(localizer *localization.SimpleLocalizer) {
-
-

-

-
{ localizer.T("loading") }
-
-
-
- { localizer.T("why_am_i_seeing") }
-
- { localizer.T("ai_companies_explanation") }
-
-
- { localizer.T("anubis_compromise") }
-
-
- { localizer.T("hack_purpose") }
-
-
- { localizer.T("jshelter_note") }
-
- { localizer.T("version_info") } { anubis.Version }
.
-
-
-
-
-}
-
templ errorPage(message, mail string, localizer *localization.SimpleLocalizer) {

diff --git a/web/index_templ.go b/web/index_templ.go
index d502689..ee72ec1 100644
--- a/web/index_templ.go
+++ b/web/index_templ.go
@@ -120,11 +120,9 @@ func base(title string, body templ.Component, impressum *config.Impressum, chall
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- if challenge != nil {
- templ_7745c5c3_Err = templ.JSONScript("anubis_challenge", challenge).Render(ctx, templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
+ templ_7745c5c3_Err = templ.JSONScript("anubis_challenge", challenge).Render(ctx, templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templ.JSONScript("anubis_base_prefix", anubis.BasePrefix).Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
@@ -137,7 +135,7 @@ func base(title string, body templ.Component, impressum *config.Impressum, chall
var templ_7745c5c3_Var7 string
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(title)
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 68, Col: 47}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 66, Col: 47}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
if templ_7745c5c3_Err != nil {
@@ -158,7 +156,7 @@ func base(title string, body templ.Component, impressum *config.Impressum, chall
var templ_7745c5c3_Var8 string
templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(localizer.T("protected_by"))
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 73, Col: 36}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 71, Col: 36}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
if templ_7745c5c3_Err != nil {
@@ -171,7 +169,7 @@ func base(title string, body templ.Component, impressum *config.Impressum, chall
var templ_7745c5c3_Var9 string
templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(localizer.T("protected_from"))
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 73, Col: 127}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 71, Col: 127}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9))
if templ_7745c5c3_Err != nil {
@@ -184,7 +182,7 @@ func base(title string, body templ.Component, impressum *config.Impressum, chall
var templ_7745c5c3_Var10 string
templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(localizer.T("made_with"))
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 75, Col: 40}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 73, Col: 40}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10))
if templ_7745c5c3_Err != nil {
@@ -197,7 +195,7 @@ func base(title string, body templ.Component, impressum *config.Impressum, chall
var templ_7745c5c3_Var11 string
templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(localizer.T("mascot_design"))
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 77, Col: 39}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 75, Col: 39}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11))
if templ_7745c5c3_Err != nil {
@@ -210,7 +208,7 @@ func base(title string, body templ.Component, impressum *config.Impressum, chall
var templ_7745c5c3_Var12 string
templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(localizer.T("celphase"))
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 77, Col: 123}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 75, Col: 123}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12))
if templ_7745c5c3_Err != nil {
@@ -236,7 +234,7 @@ func base(title string, body templ.Component, impressum *config.Impressum, chall
var templ_7745c5c3_Var13 templ.SafeURL
templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(fmt.Sprintf("%simprint", anubis.APIPrefix)))
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 81, Col: 78}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 79, Col: 78}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13))
if templ_7745c5c3_Err != nil {
@@ -247,192 +245,33 @@ func base(title string, body templ.Component, impressum *config.Impressum, chall
return templ_7745c5c3_Err
}
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, "