From 2246cae3f7020a7d93615a874e9436a9e508583d Mon Sep 17 00:00:00 2001 From: Niko Abeler Date: Tue, 8 Nov 2022 21:22:02 +0100 Subject: [PATCH] WIP micropub --- cmd/owl/web/handler.go | 70 ++++++++++++++++++++++++++++++++++++ cmd/owl/web/micropub_test.go | 47 ++++++++++++++++++++++++ cmd/owl/web/server.go | 2 ++ embed/initial/base.html | 1 + user.go | 41 +++++++++++++++------ user_test.go | 36 +++++++++++++++++++ 6 files changed, 186 insertions(+), 11 deletions(-) create mode 100644 cmd/owl/web/micropub_test.go diff --git a/cmd/owl/web/handler.go b/cmd/owl/web/handler.go index 4c5a160..6ce5e38 100644 --- a/cmd/owl/web/handler.go +++ b/cmd/owl/web/handler.go @@ -249,6 +249,76 @@ func postMediaHandler(repo *owl.Repository) func(http.ResponseWriter, *http.Requ } } +func userMicropubHandler(repo *owl.Repository) func(http.ResponseWriter, *http.Request, httprouter.Params) { + return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { + user, err := getUserFromRepo(repo, ps) + if err != nil { + println("Error getting user: ", err.Error()) + notFoundHandler(repo)(w, r) + return + } + + // verify access token + token := r.Header.Get("Authorization") + if token == "" { + w.WriteHeader(http.StatusUnauthorized) + w.Write([]byte("Unauthorized")) + return + } + token = strings.TrimPrefix(token, "Bearer ") + valid, _ := user.ValidateAccessToken(token) + if !valid { + w.WriteHeader(http.StatusUnauthorized) + w.Write([]byte("Unauthorized")) + return + } + + // parse request form + err = r.ParseForm() + if err != nil { + w.WriteHeader(http.StatusBadRequest) + w.Write([]byte("Bad request")) + return + } + h := r.Form.Get("h") + content := r.Form.Get("content") + name := r.Form.Get("name") + inReplyTo := r.Form.Get("in-reply-to") + + if h != "entry" { + w.WriteHeader(http.StatusBadRequest) + w.Write([]byte("Bad request. h must be entry")) + return + } + if content == "" || name == "" { + w.WriteHeader(http.StatusBadRequest) + w.Write([]byte("Bad request. content and name are required")) + return + } + + // create post + post, err := user.CreateNewPostFull( + owl.PostMeta{ + Title: name, + Reply: owl.Reply{ + Url: inReplyTo, + }, + }, + content, + ) + + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + w.Write([]byte("Internal server error")) + return + } + + w.WriteHeader(http.StatusCreated) + w.Header().Set("Location", post.FullUrl()) + + } +} + func userMediaHandler(repo *owl.Repository) func(http.ResponseWriter, *http.Request, httprouter.Params) { return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { filepath := ps.ByName("filepath") diff --git a/cmd/owl/web/micropub_test.go b/cmd/owl/web/micropub_test.go new file mode 100644 index 0000000..fd6e010 --- /dev/null +++ b/cmd/owl/web/micropub_test.go @@ -0,0 +1,47 @@ +package web_test + +import ( + "h4kor/owl-blogs" + main "h4kor/owl-blogs/cmd/owl/web" + "h4kor/owl-blogs/test/assertions" + "net/http" + "net/http/httptest" + "net/url" + "strconv" + "strings" + "testing" +) + +func TestMicropubMinimalArticle(t *testing.T) { + repo, user := getSingleUserTestRepo() + user.ResetPassword("testpassword") + + code, _ := user.GenerateAuthCode( + "test", "test", "test", "test", "test", + ) + token, _, _ := user.GenerateAccessToken(owl.AuthCode{ + Code: code, + ClientId: "test", + RedirectUri: "test", + CodeChallenge: "test", + CodeChallengeMethod: "test", + Scope: "test", + }) + + // Create Request and Response + form := url.Values{} + form.Add("h", "entry") + form.Add("name", "Test Article") + form.Add("content", "Test Content") + + req, err := http.NewRequest("POST", user.MicropubUrl(), strings.NewReader(form.Encode())) + req.Header.Add("Content-Type", "application/x-www-form-urlencoded") + req.Header.Add("Content-Length", strconv.Itoa(len(form.Encode()))) + req.Header.Add("Authorization", "Bearer "+token) + assertions.AssertNoError(t, err, "Error creating request") + rr := httptest.NewRecorder() + router := main.SingleUserRouter(&repo) + router.ServeHTTP(rr, req) + + assertions.AssertStatus(t, rr, http.StatusCreated) +} diff --git a/cmd/owl/web/server.go b/cmd/owl/web/server.go index 4967735..d828508 100644 --- a/cmd/owl/web/server.go +++ b/cmd/owl/web/server.go @@ -23,6 +23,7 @@ func Router(repo *owl.Repository) http.Handler { router.GET("/user/:user/posts/:post/", postHandler(repo)) router.GET("/user/:user/posts/:post/media/*filepath", postMediaHandler(repo)) router.POST("/user/:user/webmention/", userWebmentionHandler(repo)) + router.POST("/user/:user/micropub/", userMicropubHandler(repo)) router.GET("/user/:user/.well-known/oauth-authorization-server", userAuthMetadataHandler(repo)) router.NotFound = http.HandlerFunc(notFoundHandler(repo)) return router @@ -41,6 +42,7 @@ func SingleUserRouter(repo *owl.Repository) http.Handler { router.GET("/posts/:post/", postHandler(repo)) router.GET("/posts/:post/media/*filepath", postMediaHandler(repo)) router.POST("/webmention/", userWebmentionHandler(repo)) + router.POST("/micropub/", userMicropubHandler(repo)) router.GET("/.well-known/oauth-authorization-server", userAuthMetadataHandler(repo)) router.NotFound = http.HandlerFunc(notFoundHandler(repo)) return router diff --git a/embed/initial/base.html b/embed/initial/base.html index 78ad250..5fee043 100644 --- a/embed/initial/base.html +++ b/embed/initial/base.html @@ -31,6 +31,7 @@ + {{ end }}