An experimental IndieWeb site built in Go.
1package handlers
2
3import (
4 "net/http"
5
6 "github.com/puregarlic/space/services"
7 "github.com/puregarlic/space/storage"
8
9 "github.com/go-chi/chi/v5"
10 "github.com/go-chi/cors"
11 "go.hacdias.com/indielib/indieauth"
12 "go.hacdias.com/indielib/micropub"
13)
14
15func AttachIndieAuth(r chi.Router, path string, profileUrl string) {
16 svc := &services.IndieAuth{
17 ProfileURL: profileUrl,
18 Server: indieauth.NewServer(true, nil),
19 }
20
21 r.Route(path, func(r chi.Router) {
22 r.Post("/", svc.HandleAuthPOST)
23 r.Post("/token", svc.HandleToken)
24 r.Post("/accept", svc.HandleAuthApproval)
25
26 // User authentication portal
27 r.With(services.MustBasicAuth).Get("/", svc.HandleAuthGET)
28 })
29
30 storage.AddRel("authorization_endpoint", path)
31 storage.AddRel("token_endpoint", path+"/token")
32}
33
34func AttachMicropub(r chi.Router, path string, profileURL string) {
35 mp := &services.Micropub{
36 ProfileURL: profileURL,
37 }
38
39 mpHandler := micropub.NewHandler(
40 mp,
41 micropub.WithMediaEndpoint(profileURL+"micropub/media"),
42 )
43
44 r.Route(path, func(r chi.Router) {
45 // Enable CORS for browser-based clients
46 r.Use(cors.Handler(
47 cors.Options{
48 AllowedHeaders: []string{
49 "Accept",
50 "Authorization",
51 "Content-Type",
52 },
53 },
54 ))
55
56 // Require access tokens for all Micropub routes
57 r.Use(services.MustAuth)
58
59 r.Get("/", mpHandler.ServeHTTP)
60 r.Post("/", mpHandler.ServeHTTP)
61 r.Post("/media", micropub.NewMediaHandler(
62 mp.HandleMediaUpload,
63 func(r *http.Request, scope string) bool {
64 // IndieKit checks for a `media` scope, not commonly requested
65 hasMediaScope := mp.HasScope(r, scope)
66 hasCreateScope := mp.HasScope(r, "create")
67
68 return hasMediaScope || hasCreateScope
69 },
70 ).ServeHTTP)
71 })
72
73 storage.AddRel("micropub", path)
74}