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 }}