open Wormhole let (fake_post : Post.t) = { link = "https://google.com"; summary = "

@wormhole

https://google.com

This is a place on the web where \ you can search for things

#goodie #othergoodie

"; tags = [ "#goodie" ]; published = "2023-08-23"; author = "marcc.rooted"; author_link = "https://www.fosstodon.org/@marcc"; } let webfinger = {| { "subject": "acct:wormhole@galaxy.mccd.space", "links": [ { "rel": "self", "type": "application/activity+json", "href": "https://galaxy.mccd.space/actor" } ] } |} let actor = {| { "@context": [ "https://www.w3.org/ns/activitystreams", "https://w3id.org/security/v1" ], "id": "https://galaxy.mccd.space/actor", "type": "Person", "preferredUsername": "wormhole", "inbox": "https://galaxy.mccd.space/inbox", "publicKey": { "id": "https://galaxy.mccd.space/actor#main-key", "owner": "https://galaxy.mccd.space/actor", "publicKeyPem": "-----BEGIN PUBLIC KEY-----MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvqa9W2PjNYB6FDuRewSR\nAUyH2TK5iprbfuKWvCGEYq2FRccjmoluMEb0a16AyqqMeZ8J+pI7cPvqpdXm/VVV\niZx3Q5W4H8kIC3I84qAAzVs3wOQWnudk+D+hEE1Il9+yFBFvF7IoyER9axqJEb88\nYQ5okLU/346SMpMrk4wsUFnwaxdVXQPBQ0tVxqVJiLGSMlGXX/1Vl0+lnhgg+5rH\n8rfIbFX4qQC/gYbEU+VS2nzhYjdqn0maL94OrFHYNdrMBgSBOtbBFSJ+kMgojqES\n7Xhf+G9JcuCIqm0T3dHqo50MUSx8lrS78S3uO7WgPAby8qXjcL8sQEfNvJT16sjk\ndwIDAQAB\n-----END PUBLIC KEY-----" } } |} let actor_whitelist = [ "https://fosstodon.org/users/marcc"; "https://universeodon.com/users/icecreambook"; "https://mastodon.social/users/ronent"; "https://graphics.social/users/theohonohan"; ] let () = let port = Sys.getenv_opt "PORT" |> Option.map int_of_string |> Option.value ~default:8080 in let env = Sys.getenv_opt "ENV" |> Option.value ~default:"PROD" in let disable_auth = Sys.getenv_opt "DISABLE_AUTH" |> Option.value ~default:"false" in let interface = if env = "DEV" then "localhost" else "0.0.0.0" in if env = "DEV" then Post.add fake_post; if env = "DEV" then Post.add fake_post; if env = "DEV" then Post.add fake_post; if env = "DEV" then Post.add fake_post; Dream.run ~port ~interface @@ Dream.logger @@ Dream.router [ Dream.get "/static/**" (Dream.static "./static"); Dream.get "/feed.xml" (fun _ -> let posts = Post.get_all () in let maybe_latest_post = Post.latest_post () in match maybe_latest_post with | Some latest_post -> let rss_posts = posts |> List.map Post.to_rss_entry in let rss = Xml.format_rss "https://galaxy.mccd.space" (Post.published latest_post) rss_posts in Dream.respond rss ~headers:[ ("Content-Type", "application/rss+xml") ] | None -> Dream.html "No posts hav been published!"); Dream.get "/actor" (fun _ -> Dream.log "Sending actor"; Dream.respond actor ~headers:[ ("Content-Type", "application/activity+json") ]); Dream.get "/.well-known/webfinger" (fun _ -> Dream.log "Sending webfinger"; Dream.respond webfinger ~headers:[ ("Content-Type", "application/activity+json") ]); Dream.get "/" (fun request -> Dream.log "Sending greeting to %s!" (Dream.client request); let posts = Post.get_all () in Template.render posts |> Dream.html); Dream.post "/inbox" (fun request -> let%lwt body = Dream.body request in Dream.log "Got body: %s" body; let message_object = Yojson.Safe.from_string body |> Post.mastodon_post_of_yojson in let%lwt actor = User.get_user (Post.mastodon_actor message_object) in Dream.log "User found"; let pem = User.get_public_pem actor |> Result.to_option in let%lwt valid_request = Sig.verify_request pem request in let post = message_object |> Post.post_of_mastodon_post (User.name actor) in let in_whitelist = List.mem (Post.mastodon_actor message_object) actor_whitelist in match (valid_request, disable_auth, in_whitelist) with | Error e, "false", _ -> Dream.log "Error verifying request %s" Printexc.(to_string e); let code = Some 500 in Dream.json ?code "Invalid request" | Ok false, "false", _ -> Dream.log "Unauthorized request"; let code = Some 401 in Dream.json ?code "Unauthorized" | _, _, false -> Dream.log "Unauthorized request"; let code = Some 401 in Dream.json ?code "Unauthorized, not in whitelist" | _, _, _ -> post |> Post.add; message_object |> Post.yojson_of_mastodon_post |> Yojson.Safe.to_string |> Dream.log "Added post %s"; Dream.json "Added user"); ]