Skip to content

Commit

Permalink
Mostly usable now. The Planck light theme is usable.
Browse files Browse the repository at this point in the history
  • Loading branch information
MetroWind committed Sep 29, 2024
1 parent febc177 commit f6db490
Show file tree
Hide file tree
Showing 15 changed files with 446 additions and 123 deletions.
71 changes: 65 additions & 6 deletions src/app.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,7 @@ void App::handleIndex(const httplib::Request& req, httplib::Response& res)
{"session_user", session->user.name}});
std::string result = templates.render_file(
"index.html", std::move(data));
res.status = 200;
res.set_content(result, "text/html");
}

Expand Down Expand Up @@ -442,6 +443,7 @@ void App::handlePost(const httplib::Request& req, httplib::Response& res)
{"session_user", session->user.name}});
std::string result = templates.render_file(
"post.html", std::move(data));
res.status = 200;
res.set_content(std::move(result), "text/html");
}

Expand All @@ -463,6 +465,7 @@ void App::handleDrafts(const httplib::Request& req, httplib::Response& res)

std::string result = templates.render_file(
"drafts.html", std::move(data));
res.status = 200;
res.set_content(result, "text/html");
}

Expand All @@ -477,19 +480,66 @@ void App::handleCreatePostFrontEnd(const httplib::Request& req,
{"session_user", session->user.name}});
std::string result = templates.render_file(
"create_post.html", std::move(data));
res.status = 200;
res.set_content(result, "text/html");
}

void App::handleCreateDraft(const httplib::Request& req,
void App::handleSaveDraft(const httplib::Request& req,
httplib::Response& res) const
{
auto session = prepareSession(req, res);
if(!session.has_value()) return;

ASSIGN_OR_RESPOND_ERROR(Post draft, formToPost(req, session->user.name), res);
ASSIGN_OR_RESPOND_ERROR(int64_t id, data->saveDraft(std::move(draft)), res);
int64_t id;
if(draft.id.has_value())
{
id = *draft.id;
auto ok_maybe = data->editDraft(draft);
if(!ok_maybe)
{
res.status = 500;
res.set_content(errorMsg(ok_maybe.error()), "text/plain");
return;
}
}
else
{
ASSIGN_OR_RESPOND_ERROR(id, data->saveDraft(std::move(draft)),
res);
}
res.set_redirect(urlFor("edit-draft", std::to_string(id)));
}
void App::handleEditDraftFrontEnd(const httplib::Request& req,
httplib::Response& res)
{
ASSIGN_OR_RESPOND_ERROR(
int64_t id, strToNumber<int64_t>(req.path_params.at("id")).or_else(
[]([[maybe_unused]] auto _) -> E<int64_t>
{
return std::unexpected(httpError(401, "Invalid post ID"));
}), res);

auto session = prepareSession(req, res);
if(!session.has_value()) return;

ASSIGN_OR_RESPOND_ERROR(std::optional<Post> p, data->getDraft(id), res);
if(!p.has_value())
{
res.status = 404;
res.set_content("Draft not found", "text/plain");
return;
}

nlohmann::json data = baseTemplateData(req);
data.merge_patch({{"languages", config.languages},
{"session_user", session->user.name},
{"post", postToJson(*p)}});
std::string result = templates.render_file(
"edit_draft.html", std::move(data));
res.status = 200;
res.set_content(result, "text/html");
}

void App::handleEditPostFrontEnd(const httplib::Request& req,
httplib::Response& res)
Expand Down Expand Up @@ -518,6 +568,7 @@ void App::handleEditPostFrontEnd(const httplib::Request& req,
{"post", postToJson(*p)}});
std::string result = templates.render_file(
"edit_post.html", std::move(data));
res.status = 200;
res.set_content(result, "text/html");
}

Expand Down Expand Up @@ -592,6 +643,7 @@ void App::handleAttachments(const httplib::Request& req, httplib::Response& res)

std::string result = templates.render_file(
"attachments.html", std::move(data));
res.status = 200;
res.set_content(result, "text/html");
}

Expand Down Expand Up @@ -619,6 +671,7 @@ void App::handleAttachment(const httplib::Request& req, httplib::Response& res)
std::ifstream file(path);
std::string data(std::istreambuf_iterator<char>{file}, {});
file.close();
res.status = 200;
res.set_content(data, att->content_type);
}

Expand All @@ -639,7 +692,6 @@ void App::handleAttachmentUpload(const httplib::Request& req,
file.content, file.filename, file.content_type);
fs::path path = fs::path(config.attachment_dir) /
attachment_manager.path(att);
spdlog::debug("Adding attachment to {}...", path.string());
fs::path dir = path.parent_path();
if(!fs::exists(dir))
{
Expand Down Expand Up @@ -696,6 +748,7 @@ void App::handleSelectTheme(const httplib::Request& req, httplib::Response& res)
std::string_view theme = theme_obj.get_ref<const std::string&>();
res.set_header("Set-Cookie", std::format(
"planck-blog-theme={}; Max-Age=315360000", theme));
res.status = 204;
}

nlohmann::json App::postToJson(const Post& p) const
Expand Down Expand Up @@ -787,8 +840,8 @@ E<Post> App::formToPost(const httplib::Request& req, std::string_view author) co
draft.id, strToNumber<int64_t>(req.get_param_value("id")));
}
draft.title = req.get_param_value("title");
draft.abstract = req.get_param_value("abstract");
draft.raw_content = req.get_param_value("content");
draft.abstract = strip(req.get_param_value("abstract"));
draft.raw_content = strip(req.get_param_value("content"));
draft.language = req.get_param_value("language");
draft.author = author;
return draft;
Expand Down Expand Up @@ -851,6 +904,11 @@ void App::setup()
{
handleCreatePostFrontEnd(req, res);
});
server.Get(getPath("edit-draft", "id"),
[&](const httplib::Request& req, httplib::Response& res)
{
handleEditDraftFrontEnd(req, res);
});
server.Get(getPath("edit-post", "id"),
[&](const httplib::Request& req, httplib::Response& res)
{
Expand All @@ -864,7 +922,7 @@ void App::setup()
server.Post(getPath("save-draft"),
[&](const httplib::Request& req, httplib::Response& res)
{
handleCreateDraft(req, res);
handleSaveDraft(req, res);
});
server.Post(getPath("publish-from-new-draft"),
[&](const httplib::Request& req, httplib::Response& res)
Expand Down Expand Up @@ -905,6 +963,7 @@ nlohmann::json App::baseTemplateData(const httplib::Request& req) const
theme = it->second;
}
data["stylesheets"] = theme_manager.stylesheets(theme);
data["current_theme"] = theme;
return data;
}

Expand Down
4 changes: 3 additions & 1 deletion src/app.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,10 @@ class App
void handleDrafts(const httplib::Request& req, httplib::Response& res);
void handleCreatePostFrontEnd(const httplib::Request& req,
httplib::Response& res);
void handleCreateDraft(const httplib::Request& req, httplib::Response& res)
void handleSaveDraft(const httplib::Request& req, httplib::Response& res)
const;
void handleEditDraftFrontEnd(const httplib::Request& req,
httplib::Response& res);
void handleEditPostFrontEnd(const httplib::Request& req,
httplib::Response& res);
void handleSavePost(const httplib::Request& req, httplib::Response& res)
Expand Down
75 changes: 41 additions & 34 deletions src/app_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ TEST(App, CopyReqToHttplibReq)
TEST(App, LoginBringsUserToLoginURL)
{
Configuration config;
config.base_url = "http://localhost/";
auto auth = std::make_unique<AuthMock>();
EXPECT_CALL(*auth, initialURL()).WillOnce(Return("http://aaa/"));
ASSIGN_OR_FAIL(auto data, DataSourceSqlite::newFromMemory());
Expand All @@ -86,6 +87,7 @@ TEST(App, LoginBringsUserToLoginURL)
TEST(App, CanHandleOpenIDRedirect)
{
Configuration config;
config.base_url = "http://localhost/";
auto auth = std::make_unique<AuthMock>();
Tokens expected_tokens;
expected_tokens.access_token = "bbb";
Expand All @@ -108,6 +110,7 @@ TEST(App, CanHandleOpenIDRedirect)
TEST(App, OpenIDRedirectCanHandleUpstreamError)
{
Configuration config;
config.base_url = "http://localhost/";
auto auth = std::make_unique<AuthMock>();
ASSIGN_OR_FAIL(auto data, DataSourceSqlite::newFromMemory());
App app(config, std::move(auth), std::move(data));
Expand All @@ -126,49 +129,53 @@ TEST(App, OpenIDRedirectCanHandleUpstreamError)
}
}

TEST_F(UserAppTest, CanStart)
{
app->start();
app->stop();
app->wait();
}

TEST_F(UserAppTest, CanHandleIndex)
{
EXPECT_CALL(*data_source, getPostExcerpts())
.WillOnce(Return(std::vector<Post>()));

httplib::Request req;
req.set_header("Cookie", "access-token=aaa");
httplib::Response res;
app->handleIndex(req, res);
// httplib::Response::status is default to -1. Httplib will set it
// when sending the response.
EXPECT_EQ(res.status, -1);
EXPECT_TRUE(res.body.contains("<title>Test Blog</title>"));
app->start();
{
HTTPSession client;
ASSIGN_OR_FAIL(const HTTPResponse* res,
client.get("http://localhost:8080/blog"));
EXPECT_EQ(res->status, 200) << "Response body: " << res->payloadAsStr();
EXPECT_THAT(res->payloadAsStr(), HasSubstr("<title>Test Blog</title>"));
}
app->stop();
app->wait();
}

TEST_F(UserAppTest, CanHandleDrafts)
{
EXPECT_CALL(*data_source, getDrafts())
.WillOnce(Return(std::vector<Post>()));

httplib::Request req;
req.set_header("Cookie", "access-token=aaa");
httplib::Response res;
app->handleDrafts(req, res);
EXPECT_EQ(res.status, -1);
EXPECT_TRUE(res.body.contains("<title>Drafts</title>"));
app->start();
{
HTTPSession client;
ASSIGN_OR_FAIL(const HTTPResponse* res, client.get(
HTTPRequest("http://localhost:8080/blog/drafts")
.addHeader("Cookie", "planck-blog-access-token=aaa")));
EXPECT_EQ(res->status, 200) << "Response body: " << res->payloadAsStr();
EXPECT_THAT(res->payloadAsStr(), HasSubstr("<title>Drafts</title>"));
}
app->stop();
app->wait();
}

TEST_F(UserAppTest, CanHandleCreatePostFrontEnd)
{
httplib::Request req;
req.set_header("Cookie", "access-token=aaa");
httplib::Response res;
app->handleCreatePostFrontEnd(req, res);
EXPECT_EQ(res.status, -1);
EXPECT_TRUE(res.body.contains("<title>New Post</title>"));
app->start();
{
HTTPSession client;
ASSIGN_OR_FAIL(const HTTPResponse* res, client.get(
HTTPRequest("http://localhost:8080/blog/create-post")
.addHeader("Cookie", "planck-blog-access-token=aaa")));
EXPECT_EQ(res->status, 200) << "Response body: " << res->payloadAsStr();
EXPECT_THAT(res->payloadAsStr(), HasSubstr("<title>New Post</title>"));
}
app->stop();
app->wait();
}

TEST_F(UserAppTest, CanHandleCreateDraft)
Expand All @@ -189,7 +196,7 @@ TEST_F(UserAppTest, CanHandleCreateDraft)
HTTPRequest("http://localhost:8080/blog/save-draft").setPayload(
"title=aaa&abstract=bbb&language=ccc&markup=CommonMark&"
"content=ddd")
.addHeader("Cookie", "access-token=aaa")
.addHeader("Cookie", "planck-blog-access-token=aaa")
.setContentType("application/x-www-form-urlencoded")));

EXPECT_EQ(res->status, 302) << "Response body: " << res->payloadAsStr();
Expand Down Expand Up @@ -220,7 +227,7 @@ TEST_F(UserAppTest, CanHandlePublishFromNewDraft)
.setPayload(
"title=aaa&abstract=bbb&language=ccc&markup=CommonMark&"
"content=ddd")
.addHeader("Cookie", "access-token=aaa")
.addHeader("Cookie", "planck-blog-access-token=aaa")
.setContentType("application/x-www-form-urlencoded")));

EXPECT_EQ(res->status, 302) << "Response body: " << res->payloadAsStr();
Expand Down Expand Up @@ -250,7 +257,7 @@ TEST_F(UserAppTest, CanHandlePost)
HTTPSession client;
ASSIGN_OR_FAIL(const HTTPResponse* res,
client.get(HTTPRequest("http://localhost:8080/blog/p/1")
.addHeader("Cookie", "access-token=aaa")));
.addHeader("Cookie", "planck-blog-access-token=aaa")));
EXPECT_EQ(res->status, 200) << "Response body: " << res->payloadAsStr();
EXPECT_THAT(res->payloadAsStr(), HasSubstr("<h1>aaa</h1>"));
EXPECT_THAT(res->payloadAsStr(),
Expand All @@ -277,7 +284,7 @@ TEST_F(UserAppTest, CanHandleEditPostFrontEnd)
HTTPSession client;
ASSIGN_OR_FAIL(const HTTPResponse* res, client.get(
HTTPRequest("http://localhost:8080/blog/edit-post/1")
.addHeader("Cookie", "access-token=aaa")));
.addHeader("Cookie", "planck-blog-access-token=aaa")));

EXPECT_EQ(res->status, 200) << "Response body: " << res->payloadAsStr();
}
Expand Down Expand Up @@ -305,7 +312,7 @@ TEST_F(UserAppTest, CanHandleSavePost)
HTTPRequest("http://localhost:8080/blog/save-post").setPayload(
"title=aaa&abstract=bbb&language=ccc&markup=CommonMark&"
"content=ddd&id=1")
.addHeader("Cookie", "access-token=aaa")
.addHeader("Cookie", "planck-blog-access-token=aaa")
.setContentType("application/x-www-form-urlencoded")));

EXPECT_EQ(res->status, 302) << "Response body: " << res->payloadAsStr();
Expand All @@ -331,7 +338,7 @@ TEST_F(UserAppTest, CanHandleAttachments)
HTTPSession client;
ASSIGN_OR_FAIL(const HTTPResponse* res, client.get(
HTTPRequest("http://localhost:8080/blog/attachments")
.addHeader("Cookie", "access-token=aaa")));
.addHeader("Cookie", "planck-blog-access-token=aaa")));

EXPECT_EQ(res->status, 200) << "Response body: " << res->payloadAsStr();
EXPECT_THAT(res->payloadAsStr(), HasSubstr(
Expand Down
5 changes: 4 additions & 1 deletion src/url.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,10 @@ URL& URL::operator=(const URL& rhs)
curl_url_cleanup(url);
url = nullptr;
}
url = curl_url_dup(rhs.url);
if(rhs.url != nullptr)
{
url = curl_url_dup(rhs.url);
}
return *this;
}

Expand Down
Loading

0 comments on commit f6db490

Please sign in to comment.